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