• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "jni.h"
2 #include "GraphicsJNI.h"
3 #include "NIOBuffer.h"
4 #include "SkPicture.h"
5 #include "SkRegion.h"
6 #include <android_runtime/AndroidRuntime.h>
7 
8 //#define REPORT_SIZE_TO_JVM
9 //#define TRACK_LOCK_COUNT
10 
doThrow(JNIEnv * env,const char * exc,const char * msg)11 void doThrow(JNIEnv* env, const char* exc, const char* msg) {
12     // don't throw a new exception if we already have one pending
13     if (env->ExceptionCheck() == JNI_FALSE) {
14         jclass npeClazz;
15 
16         npeClazz = env->FindClass(exc);
17         LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc);
18 
19         env->ThrowNew(npeClazz, msg);
20     }
21 }
22 
doThrowNPE(JNIEnv * env)23 void doThrowNPE(JNIEnv* env) {
24     doThrow(env, "java/lang/NullPointerException");
25 }
26 
doThrowAIOOBE(JNIEnv * env)27 void doThrowAIOOBE(JNIEnv* env) {
28     doThrow(env, "java/lang/ArrayIndexOutOfBoundsException");
29 }
30 
doThrowRE(JNIEnv * env,const char * msg)31 void doThrowRE(JNIEnv* env, const char* msg) {
32     doThrow(env, "java/lang/RuntimeException", msg);
33 }
34 
doThrowIAE(JNIEnv * env,const char * msg)35 void doThrowIAE(JNIEnv* env, const char* msg) {
36     doThrow(env, "java/lang/IllegalArgumentException", msg);
37 }
38 
doThrowISE(JNIEnv * env,const char * msg)39 void doThrowISE(JNIEnv* env, const char* msg) {
40     doThrow(env, "java/lang/IllegalStateException", msg);
41 }
42 
doThrowOOME(JNIEnv * env,const char * msg)43 void doThrowOOME(JNIEnv* env, const char* msg) {
44     doThrow(env, "java/lang/OutOfMemoryError", msg);
45 }
46 
hasException(JNIEnv * env)47 bool GraphicsJNI::hasException(JNIEnv *env) {
48     if (env->ExceptionCheck() != 0) {
49         LOGE("*** Uncaught exception returned from Java call!\n");
50         env->ExceptionDescribe();
51         return true;
52     }
53     return false;
54 }
55 
56 ///////////////////////////////////////////////////////////////////////////////
57 
AutoJavaFloatArray(JNIEnv * env,jfloatArray array,int minLength)58 AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
59                                        int minLength)
60 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
61     SkASSERT(env);
62     if (array) {
63         fLen = env->GetArrayLength(array);
64         if (fLen < minLength) {
65             sk_throw();
66         }
67         fPtr = env->GetFloatArrayElements(array, NULL);
68     }
69 }
70 
~AutoJavaFloatArray()71 AutoJavaFloatArray::~AutoJavaFloatArray() {
72     if (fPtr) {
73         fEnv->ReleaseFloatArrayElements(fArray, fPtr, 0);
74     }
75 }
76 
AutoJavaIntArray(JNIEnv * env,jintArray array,int minLength)77 AutoJavaIntArray::AutoJavaIntArray(JNIEnv* env, jintArray array,
78                                        int minLength)
79 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
80     SkASSERT(env);
81     if (array) {
82         fLen = env->GetArrayLength(array);
83         if (fLen < minLength) {
84             sk_throw();
85         }
86         fPtr = env->GetIntArrayElements(array, NULL);
87     }
88 }
89 
~AutoJavaIntArray()90 AutoJavaIntArray::~AutoJavaIntArray() {
91     if (fPtr) {
92         fEnv->ReleaseIntArrayElements(fArray, fPtr, 0);
93     }
94 }
95 
AutoJavaShortArray(JNIEnv * env,jshortArray array,int minLength)96 AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array,
97                                        int minLength)
98 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
99     SkASSERT(env);
100     if (array) {
101         fLen = env->GetArrayLength(array);
102         if (fLen < minLength) {
103             sk_throw();
104         }
105         fPtr = env->GetShortArrayElements(array, NULL);
106     }
107 }
108 
~AutoJavaShortArray()109 AutoJavaShortArray::~AutoJavaShortArray() {
110     if (fPtr) {
111         fEnv->ReleaseShortArrayElements(fArray, fPtr, 0);
112     }
113 }
114 
AutoJavaByteArray(JNIEnv * env,jbyteArray array,int minLength)115 AutoJavaByteArray::AutoJavaByteArray(JNIEnv* env, jbyteArray array,
116                                        int minLength)
117 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
118     SkASSERT(env);
119     if (array) {
120         fLen = env->GetArrayLength(array);
121         if (fLen < minLength) {
122             sk_throw();
123         }
124         fPtr = env->GetByteArrayElements(array, NULL);
125     }
126 }
127 
~AutoJavaByteArray()128 AutoJavaByteArray::~AutoJavaByteArray() {
129     if (fPtr) {
130         fEnv->ReleaseByteArrayElements(fArray, fPtr, 0);
131     }
132 }
133 
134 ///////////////////////////////////////////////////////////////////////////////
135 
136 static jclass   gRect_class;
137 static jfieldID gRect_leftFieldID;
138 static jfieldID gRect_topFieldID;
139 static jfieldID gRect_rightFieldID;
140 static jfieldID gRect_bottomFieldID;
141 
142 static jclass   gRectF_class;
143 static jfieldID gRectF_leftFieldID;
144 static jfieldID gRectF_topFieldID;
145 static jfieldID gRectF_rightFieldID;
146 static jfieldID gRectF_bottomFieldID;
147 
148 static jclass   gPoint_class;
149 static jfieldID gPoint_xFieldID;
150 static jfieldID gPoint_yFieldID;
151 
152 static jclass   gPointF_class;
153 static jfieldID gPointF_xFieldID;
154 static jfieldID gPointF_yFieldID;
155 
156 static jclass   gBitmap_class;
157 static jfieldID gBitmap_nativeInstanceID;
158 static jmethodID gBitmap_constructorMethodID;
159 static jmethodID gBitmap_allocBufferMethodID;
160 
161 static jclass   gBitmapConfig_class;
162 static jfieldID gBitmapConfig_nativeInstanceID;
163 
164 static jclass   gCanvas_class;
165 static jfieldID gCanvas_nativeInstanceID;
166 
167 static jclass   gPaint_class;
168 static jfieldID gPaint_nativeInstanceID;
169 
170 static jclass   gPicture_class;
171 static jfieldID gPicture_nativeInstanceID;
172 
173 static jclass   gRegion_class;
174 static jfieldID gRegion_nativeInstanceID;
175 static jmethodID gRegion_constructorMethodID;
176 
177 static jobject   gVMRuntime_singleton;
178 static jmethodID gVMRuntime_trackExternalAllocationMethodID;
179 static jmethodID gVMRuntime_trackExternalFreeMethodID;
180 
181 ///////////////////////////////////////////////////////////////////////////////
182 
get_jrect(JNIEnv * env,jobject obj,int * L,int * T,int * R,int * B)183 void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B)
184 {
185     SkASSERT(env->IsInstanceOf(obj, gRect_class));
186 
187     *L = env->GetIntField(obj, gRect_leftFieldID);
188     *T = env->GetIntField(obj, gRect_topFieldID);
189     *R = env->GetIntField(obj, gRect_rightFieldID);
190     *B = env->GetIntField(obj, gRect_bottomFieldID);
191 }
192 
set_jrect(JNIEnv * env,jobject obj,int L,int T,int R,int B)193 void GraphicsJNI::set_jrect(JNIEnv* env, jobject obj, int L, int T, int R, int B)
194 {
195     SkASSERT(env->IsInstanceOf(obj, gRect_class));
196 
197     env->SetIntField(obj, gRect_leftFieldID, L);
198     env->SetIntField(obj, gRect_topFieldID, T);
199     env->SetIntField(obj, gRect_rightFieldID, R);
200     env->SetIntField(obj, gRect_bottomFieldID, B);
201 }
202 
jrect_to_irect(JNIEnv * env,jobject obj,SkIRect * ir)203 SkIRect* GraphicsJNI::jrect_to_irect(JNIEnv* env, jobject obj, SkIRect* ir)
204 {
205     SkASSERT(env->IsInstanceOf(obj, gRect_class));
206 
207     ir->set(env->GetIntField(obj, gRect_leftFieldID),
208             env->GetIntField(obj, gRect_topFieldID),
209             env->GetIntField(obj, gRect_rightFieldID),
210             env->GetIntField(obj, gRect_bottomFieldID));
211     return ir;
212 }
213 
irect_to_jrect(const SkIRect & ir,JNIEnv * env,jobject obj)214 void GraphicsJNI::irect_to_jrect(const SkIRect& ir, JNIEnv* env, jobject obj)
215 {
216     SkASSERT(env->IsInstanceOf(obj, gRect_class));
217 
218     env->SetIntField(obj, gRect_leftFieldID, ir.fLeft);
219     env->SetIntField(obj, gRect_topFieldID, ir.fTop);
220     env->SetIntField(obj, gRect_rightFieldID, ir.fRight);
221     env->SetIntField(obj, gRect_bottomFieldID, ir.fBottom);
222 }
223 
jrectf_to_rect(JNIEnv * env,jobject obj,SkRect * r)224 SkRect* GraphicsJNI::jrectf_to_rect(JNIEnv* env, jobject obj, SkRect* r)
225 {
226     SkASSERT(env->IsInstanceOf(obj, gRectF_class));
227 
228     r->set(SkFloatToScalar(env->GetFloatField(obj, gRectF_leftFieldID)),
229            SkFloatToScalar(env->GetFloatField(obj, gRectF_topFieldID)),
230            SkFloatToScalar(env->GetFloatField(obj, gRectF_rightFieldID)),
231            SkFloatToScalar(env->GetFloatField(obj, gRectF_bottomFieldID)));
232     return r;
233 }
234 
jrect_to_rect(JNIEnv * env,jobject obj,SkRect * r)235 SkRect* GraphicsJNI::jrect_to_rect(JNIEnv* env, jobject obj, SkRect* r)
236 {
237     SkASSERT(env->IsInstanceOf(obj, gRect_class));
238 
239     r->set(SkIntToScalar(env->GetIntField(obj, gRect_leftFieldID)),
240            SkIntToScalar(env->GetIntField(obj, gRect_topFieldID)),
241            SkIntToScalar(env->GetIntField(obj, gRect_rightFieldID)),
242            SkIntToScalar(env->GetIntField(obj, gRect_bottomFieldID)));
243     return r;
244 }
245 
rect_to_jrectf(const SkRect & r,JNIEnv * env,jobject obj)246 void GraphicsJNI::rect_to_jrectf(const SkRect& r, JNIEnv* env, jobject obj)
247 {
248     SkASSERT(env->IsInstanceOf(obj, gRectF_class));
249 
250     env->SetFloatField(obj, gRectF_leftFieldID, SkScalarToFloat(r.fLeft));
251     env->SetFloatField(obj, gRectF_topFieldID, SkScalarToFloat(r.fTop));
252     env->SetFloatField(obj, gRectF_rightFieldID, SkScalarToFloat(r.fRight));
253     env->SetFloatField(obj, gRectF_bottomFieldID, SkScalarToFloat(r.fBottom));
254 }
255 
jpoint_to_ipoint(JNIEnv * env,jobject obj,SkIPoint * point)256 SkIPoint* GraphicsJNI::jpoint_to_ipoint(JNIEnv* env, jobject obj, SkIPoint* point)
257 {
258     SkASSERT(env->IsInstanceOf(obj, gPoint_class));
259 
260     point->set(env->GetIntField(obj, gPoint_xFieldID),
261                env->GetIntField(obj, gPoint_yFieldID));
262     return point;
263 }
264 
ipoint_to_jpoint(const SkIPoint & ir,JNIEnv * env,jobject obj)265 void GraphicsJNI::ipoint_to_jpoint(const SkIPoint& ir, JNIEnv* env, jobject obj)
266 {
267     SkASSERT(env->IsInstanceOf(obj, gPoint_class));
268 
269     env->SetIntField(obj, gPoint_xFieldID, ir.fX);
270     env->SetIntField(obj, gPoint_yFieldID, ir.fY);
271 }
272 
jpointf_to_point(JNIEnv * env,jobject obj,SkPoint * point)273 SkPoint* GraphicsJNI::jpointf_to_point(JNIEnv* env, jobject obj, SkPoint* point)
274 {
275     SkASSERT(env->IsInstanceOf(obj, gPointF_class));
276 
277     point->set(SkFloatToScalar(env->GetIntField(obj, gPointF_xFieldID)),
278                SkFloatToScalar(env->GetIntField(obj, gPointF_yFieldID)));
279     return point;
280 }
281 
point_to_jpointf(const SkPoint & r,JNIEnv * env,jobject obj)282 void GraphicsJNI::point_to_jpointf(const SkPoint& r, JNIEnv* env, jobject obj)
283 {
284     SkASSERT(env->IsInstanceOf(obj, gPointF_class));
285 
286     env->SetFloatField(obj, gPointF_xFieldID, SkScalarToFloat(r.fX));
287     env->SetFloatField(obj, gPointF_yFieldID, SkScalarToFloat(r.fY));
288 }
289 
getNativeBitmap(JNIEnv * env,jobject bitmap)290 SkBitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
291     SkASSERT(env);
292     SkASSERT(bitmap);
293     SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
294     SkBitmap* b = (SkBitmap*)env->GetIntField(bitmap, gBitmap_nativeInstanceID);
295     SkASSERT(b);
296     return b;
297 }
298 
getNativeBitmapConfig(JNIEnv * env,jobject jconfig)299 SkBitmap::Config GraphicsJNI::getNativeBitmapConfig(JNIEnv* env,
300                                                     jobject jconfig) {
301     SkASSERT(env);
302     if (NULL == jconfig) {
303         return SkBitmap::kNo_Config;
304     }
305     SkASSERT(env->IsInstanceOf(jconfig, gBitmapConfig_class));
306     int c = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID);
307     if (c < 0 || c >= SkBitmap::kConfigCount) {
308         c = SkBitmap::kNo_Config;
309     }
310     return static_cast<SkBitmap::Config>(c);
311 }
312 
getNativeCanvas(JNIEnv * env,jobject canvas)313 SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) {
314     SkASSERT(env);
315     SkASSERT(canvas);
316     SkASSERT(env->IsInstanceOf(canvas, gCanvas_class));
317     SkCanvas* c = (SkCanvas*)env->GetIntField(canvas, gCanvas_nativeInstanceID);
318     SkASSERT(c);
319     return c;
320 }
321 
getNativePaint(JNIEnv * env,jobject paint)322 SkPaint* GraphicsJNI::getNativePaint(JNIEnv* env, jobject paint) {
323     SkASSERT(env);
324     SkASSERT(paint);
325     SkASSERT(env->IsInstanceOf(paint, gPaint_class));
326     SkPaint* p = (SkPaint*)env->GetIntField(paint, gPaint_nativeInstanceID);
327     SkASSERT(p);
328     return p;
329 }
330 
getNativePicture(JNIEnv * env,jobject picture)331 SkPicture* GraphicsJNI::getNativePicture(JNIEnv* env, jobject picture)
332 {
333     SkASSERT(env);
334     SkASSERT(picture);
335     SkASSERT(env->IsInstanceOf(picture, gPicture_class));
336     SkPicture* p = (SkPicture*)env->GetIntField(picture, gPicture_nativeInstanceID);
337     SkASSERT(p);
338     return p;
339 }
340 
getNativeRegion(JNIEnv * env,jobject region)341 SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region)
342 {
343     SkASSERT(env);
344     SkASSERT(region);
345     SkASSERT(env->IsInstanceOf(region, gRegion_class));
346     SkRegion* r = (SkRegion*)env->GetIntField(region, gRegion_nativeInstanceID);
347     SkASSERT(r);
348     return r;
349 }
350 
351 ///////////////////////////////////////////////////////////////////////////////////////////
352 
createBitmap(JNIEnv * env,SkBitmap * bitmap,bool isMutable,jbyteArray ninepatch,int density)353 jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
354                                   jbyteArray ninepatch, int density)
355 {
356     SkASSERT(bitmap != NULL);
357     SkASSERT(NULL != bitmap->pixelRef());
358 
359     jobject obj = env->AllocObject(gBitmap_class);
360     if (obj) {
361         env->CallVoidMethod(obj, gBitmap_constructorMethodID,
362                             (jint)bitmap, isMutable, ninepatch, density);
363         if (hasException(env)) {
364             obj = NULL;
365         }
366     }
367     return obj;
368 }
369 
createRegion(JNIEnv * env,SkRegion * region)370 jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region)
371 {
372     SkASSERT(region != NULL);
373     jobject obj = env->AllocObject(gRegion_class);
374     if (obj) {
375         env->CallVoidMethod(obj, gRegion_constructorMethodID, (jint)region, 0);
376         if (hasException(env)) {
377             obj = NULL;
378         }
379     }
380     return obj;
381 }
382 
383 #include "SkPixelRef.h"
384 
vm2env(JavaVM * vm)385 static JNIEnv* vm2env(JavaVM* vm)
386 {
387     JNIEnv* env = NULL;
388     if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK || NULL == env)
389     {
390         SkDebugf("------- [%p] vm->GetEnv() failed\n", vm);
391         sk_throw();
392     }
393     return env;
394 }
395 
396 #ifdef TRACK_LOCK_COUNT
397     static int gLockCount;
398 #endif
399 
400 ///////////////////////////////////////////////////////////////////////////////
401 
402 #include "SkMallocPixelRef.h"
403 
404 /*  Extend SkMallocPixelRef to inform the VM when we free up the storage
405 */
406 class AndroidPixelRef : public SkMallocPixelRef {
407 public:
408     /** Allocate the specified buffer for pixels. The memory is freed when the
409         last owner of this pixelref is gone. Our caller has already informed
410         the VM of our allocation.
411     */
AndroidPixelRef(JNIEnv * env,void * storage,size_t size,SkColorTable * ctable)412     AndroidPixelRef(JNIEnv* env, void* storage, size_t size,
413             SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable) {
414         SkASSERT(storage);
415         SkASSERT(env);
416 
417         if (env->GetJavaVM(&fVM) != JNI_OK) {
418             SkDebugf("------ [%p] env->GetJavaVM failed\n", env);
419             sk_throw();
420         }
421     }
422 
~AndroidPixelRef()423     virtual ~AndroidPixelRef() {
424         JNIEnv* env = vm2env(fVM);
425 //        SkDebugf("-------------- inform VM we're releasing %d bytes\n", this->getSize());
426         jlong jsize = this->getSize();  // the VM wants longs for the size
427         env->CallVoidMethod(gVMRuntime_singleton,
428                             gVMRuntime_trackExternalFreeMethodID,
429                             jsize);
430         if (GraphicsJNI::hasException(env)) {
431             env->ExceptionClear();
432         }
433     }
434 
435 private:
436     JavaVM* fVM;
437 };
438 
setJavaPixelRef(JNIEnv * env,SkBitmap * bitmap,SkColorTable * ctable,bool reportSizeToVM)439 bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
440                                   SkColorTable* ctable, bool reportSizeToVM) {
441     Sk64 size64 = bitmap->getSize64();
442     if (size64.isNeg() || !size64.is32()) {
443         doThrow(env, "java/lang/IllegalArgumentException",
444                      "bitmap size exceeds 32bits");
445         return false;
446     }
447 
448     size_t size = size64.get32();
449     jlong jsize = size;  // the VM wants longs for the size
450     if (reportSizeToVM) {
451         //    SkDebugf("-------------- inform VM we've allocated %d bytes\n", size);
452         bool r = env->CallBooleanMethod(gVMRuntime_singleton,
453                                     gVMRuntime_trackExternalAllocationMethodID,
454                                     jsize);
455         if (GraphicsJNI::hasException(env)) {
456             return false;
457         }
458         if (!r) {
459             LOGE("VM won't let us allocate %zd bytes\n", size);
460             doThrowOOME(env, "bitmap size exceeds VM budget");
461             return false;
462         }
463     }
464     // call the version of malloc that returns null on failure
465     void* addr = sk_malloc_flags(size, 0);
466     if (NULL == addr) {
467         if (reportSizeToVM) {
468             //        SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size);
469             // we didn't actually allocate it, so inform the VM
470             env->CallVoidMethod(gVMRuntime_singleton,
471                                  gVMRuntime_trackExternalFreeMethodID,
472                                  jsize);
473             if (!GraphicsJNI::hasException(env)) {
474                 doThrowOOME(env, "bitmap size too large for malloc");
475             }
476         }
477         return false;
478     }
479 
480     SkPixelRef* pr = reportSizeToVM ?
481                         new AndroidPixelRef(env, addr, size, ctable) :
482                         new SkMallocPixelRef(addr, size, ctable);
483     bitmap->setPixelRef(pr)->unref();
484     // since we're already allocated, we lockPixels right away
485     // HeapAllocator behaves this way too
486     bitmap->lockPixels();
487     return true;
488 }
489 
490 ///////////////////////////////////////////////////////////////////////////////
491 
JavaPixelAllocator(JNIEnv * env,bool reportSizeToVM)492 JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM)
493     : fEnv(env), fReportSizeToVM(reportSizeToVM) {}
494 
allocPixelRef(SkBitmap * bitmap,SkColorTable * ctable)495 bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
496     return GraphicsJNI::setJavaPixelRef(fEnv, bitmap, ctable, fReportSizeToVM);
497 }
498 
499 ////////////////////////////////////////////////////////////////////////////////
500 
make_globalref(JNIEnv * env,const char classname[])501 static jclass make_globalref(JNIEnv* env, const char classname[])
502 {
503     jclass c = env->FindClass(classname);
504     SkASSERT(c);
505     return (jclass)env->NewGlobalRef(c);
506 }
507 
getFieldIDCheck(JNIEnv * env,jclass clazz,const char fieldname[],const char type[])508 static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
509                                 const char fieldname[], const char type[])
510 {
511     jfieldID id = env->GetFieldID(clazz, fieldname, type);
512     SkASSERT(id);
513     return id;
514 }
515 
register_android_graphics_Graphics(JNIEnv * env)516 int register_android_graphics_Graphics(JNIEnv* env)
517 {
518     jmethodID m;
519     jclass c;
520 
521     gRect_class = make_globalref(env, "android/graphics/Rect");
522     gRect_leftFieldID = getFieldIDCheck(env, gRect_class, "left", "I");
523     gRect_topFieldID = getFieldIDCheck(env, gRect_class, "top", "I");
524     gRect_rightFieldID = getFieldIDCheck(env, gRect_class, "right", "I");
525     gRect_bottomFieldID = getFieldIDCheck(env, gRect_class, "bottom", "I");
526 
527     gRectF_class = make_globalref(env, "android/graphics/RectF");
528     gRectF_leftFieldID = getFieldIDCheck(env, gRectF_class, "left", "F");
529     gRectF_topFieldID = getFieldIDCheck(env, gRectF_class, "top", "F");
530     gRectF_rightFieldID = getFieldIDCheck(env, gRectF_class, "right", "F");
531     gRectF_bottomFieldID = getFieldIDCheck(env, gRectF_class, "bottom", "F");
532 
533     gPoint_class = make_globalref(env, "android/graphics/Point");
534     gPoint_xFieldID = getFieldIDCheck(env, gPoint_class, "x", "I");
535     gPoint_yFieldID = getFieldIDCheck(env, gPoint_class, "y", "I");
536 
537     gPointF_class = make_globalref(env, "android/graphics/PointF");
538     gPointF_xFieldID = getFieldIDCheck(env, gPointF_class, "x", "F");
539     gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F");
540 
541     gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
542     gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I");
543     gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
544                                             "(IZ[BI)V");
545 
546     gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config");
547     gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class,
548                                                      "nativeInt", "I");
549 
550     gCanvas_class = make_globalref(env, "android/graphics/Canvas");
551     gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvas", "I");
552 
553     gPaint_class = make_globalref(env, "android/graphics/Paint");
554     gPaint_nativeInstanceID = getFieldIDCheck(env, gPaint_class, "mNativePaint", "I");
555 
556     gPicture_class = make_globalref(env, "android/graphics/Picture");
557     gPicture_nativeInstanceID = getFieldIDCheck(env, gPicture_class, "mNativePicture", "I");
558 
559     gRegion_class = make_globalref(env, "android/graphics/Region");
560     gRegion_nativeInstanceID = getFieldIDCheck(env, gRegion_class, "mNativeRegion", "I");
561     gRegion_constructorMethodID = env->GetMethodID(gRegion_class, "<init>",
562         "(II)V");
563 
564     // Get the VMRuntime class.
565     c = env->FindClass("dalvik/system/VMRuntime");
566     SkASSERT(c);
567     // Look up VMRuntime.getRuntime().
568     m = env->GetStaticMethodID(c, "getRuntime", "()Ldalvik/system/VMRuntime;");
569     SkASSERT(m);
570     // Call VMRuntime.getRuntime() and hold onto its result.
571     gVMRuntime_singleton = env->CallStaticObjectMethod(c, m);
572     SkASSERT(gVMRuntime_singleton);
573     gVMRuntime_singleton = (jobject)env->NewGlobalRef(gVMRuntime_singleton);
574     // Look up the VMRuntime methods we'll be using.
575     gVMRuntime_trackExternalAllocationMethodID =
576                         env->GetMethodID(c, "trackExternalAllocation", "(J)Z");
577     gVMRuntime_trackExternalFreeMethodID =
578                             env->GetMethodID(c, "trackExternalFree", "(J)V");
579 
580     NIOBuffer::RegisterJNI(env);
581 
582     return 0;
583 }
584 
585