Graphics.cpp revision edf7223bc2972b99306e31c5b424c365d9248817
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 gLargeBitmap_class; 172static jmethodID gLargeBitmap_constructorMethodID; 173 174static jclass gCanvas_class; 175static jfieldID gCanvas_nativeInstanceID; 176 177static jclass gPaint_class; 178static jfieldID gPaint_nativeInstanceID; 179 180static jclass gPicture_class; 181static jfieldID gPicture_nativeInstanceID; 182 183static jclass gRegion_class; 184static jfieldID gRegion_nativeInstanceID; 185static jmethodID gRegion_constructorMethodID; 186 187static jobject gVMRuntime_singleton; 188static jmethodID gVMRuntime_trackExternalAllocationMethodID; 189static jmethodID gVMRuntime_trackExternalFreeMethodID; 190 191/////////////////////////////////////////////////////////////////////////////// 192 193void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B) 194{ 195 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 196 197 *L = env->GetIntField(obj, gRect_leftFieldID); 198 *T = env->GetIntField(obj, gRect_topFieldID); 199 *R = env->GetIntField(obj, gRect_rightFieldID); 200 *B = env->GetIntField(obj, gRect_bottomFieldID); 201} 202 203void GraphicsJNI::set_jrect(JNIEnv* env, jobject obj, int L, int T, int R, int B) 204{ 205 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 206 207 env->SetIntField(obj, gRect_leftFieldID, L); 208 env->SetIntField(obj, gRect_topFieldID, T); 209 env->SetIntField(obj, gRect_rightFieldID, R); 210 env->SetIntField(obj, gRect_bottomFieldID, B); 211} 212 213SkIRect* GraphicsJNI::jrect_to_irect(JNIEnv* env, jobject obj, SkIRect* ir) 214{ 215 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 216 217 ir->set(env->GetIntField(obj, gRect_leftFieldID), 218 env->GetIntField(obj, gRect_topFieldID), 219 env->GetIntField(obj, gRect_rightFieldID), 220 env->GetIntField(obj, gRect_bottomFieldID)); 221 return ir; 222} 223 224void GraphicsJNI::irect_to_jrect(const SkIRect& ir, JNIEnv* env, jobject obj) 225{ 226 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 227 228 env->SetIntField(obj, gRect_leftFieldID, ir.fLeft); 229 env->SetIntField(obj, gRect_topFieldID, ir.fTop); 230 env->SetIntField(obj, gRect_rightFieldID, ir.fRight); 231 env->SetIntField(obj, gRect_bottomFieldID, ir.fBottom); 232} 233 234SkRect* GraphicsJNI::jrectf_to_rect(JNIEnv* env, jobject obj, SkRect* r) 235{ 236 SkASSERT(env->IsInstanceOf(obj, gRectF_class)); 237 238 r->set(SkFloatToScalar(env->GetFloatField(obj, gRectF_leftFieldID)), 239 SkFloatToScalar(env->GetFloatField(obj, gRectF_topFieldID)), 240 SkFloatToScalar(env->GetFloatField(obj, gRectF_rightFieldID)), 241 SkFloatToScalar(env->GetFloatField(obj, gRectF_bottomFieldID))); 242 return r; 243} 244 245SkRect* GraphicsJNI::jrect_to_rect(JNIEnv* env, jobject obj, SkRect* r) 246{ 247 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 248 249 r->set(SkIntToScalar(env->GetIntField(obj, gRect_leftFieldID)), 250 SkIntToScalar(env->GetIntField(obj, gRect_topFieldID)), 251 SkIntToScalar(env->GetIntField(obj, gRect_rightFieldID)), 252 SkIntToScalar(env->GetIntField(obj, gRect_bottomFieldID))); 253 return r; 254} 255 256void GraphicsJNI::rect_to_jrectf(const SkRect& r, JNIEnv* env, jobject obj) 257{ 258 SkASSERT(env->IsInstanceOf(obj, gRectF_class)); 259 260 env->SetFloatField(obj, gRectF_leftFieldID, SkScalarToFloat(r.fLeft)); 261 env->SetFloatField(obj, gRectF_topFieldID, SkScalarToFloat(r.fTop)); 262 env->SetFloatField(obj, gRectF_rightFieldID, SkScalarToFloat(r.fRight)); 263 env->SetFloatField(obj, gRectF_bottomFieldID, SkScalarToFloat(r.fBottom)); 264} 265 266SkIPoint* GraphicsJNI::jpoint_to_ipoint(JNIEnv* env, jobject obj, SkIPoint* point) 267{ 268 SkASSERT(env->IsInstanceOf(obj, gPoint_class)); 269 270 point->set(env->GetIntField(obj, gPoint_xFieldID), 271 env->GetIntField(obj, gPoint_yFieldID)); 272 return point; 273} 274 275void GraphicsJNI::ipoint_to_jpoint(const SkIPoint& ir, JNIEnv* env, jobject obj) 276{ 277 SkASSERT(env->IsInstanceOf(obj, gPoint_class)); 278 279 env->SetIntField(obj, gPoint_xFieldID, ir.fX); 280 env->SetIntField(obj, gPoint_yFieldID, ir.fY); 281} 282 283SkPoint* GraphicsJNI::jpointf_to_point(JNIEnv* env, jobject obj, SkPoint* point) 284{ 285 SkASSERT(env->IsInstanceOf(obj, gPointF_class)); 286 287 point->set(SkFloatToScalar(env->GetIntField(obj, gPointF_xFieldID)), 288 SkFloatToScalar(env->GetIntField(obj, gPointF_yFieldID))); 289 return point; 290} 291 292void GraphicsJNI::point_to_jpointf(const SkPoint& r, JNIEnv* env, jobject obj) 293{ 294 SkASSERT(env->IsInstanceOf(obj, gPointF_class)); 295 296 env->SetFloatField(obj, gPointF_xFieldID, SkScalarToFloat(r.fX)); 297 env->SetFloatField(obj, gPointF_yFieldID, SkScalarToFloat(r.fY)); 298} 299 300SkBitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) { 301 SkASSERT(env); 302 SkASSERT(bitmap); 303 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class)); 304 SkBitmap* b = (SkBitmap*)env->GetIntField(bitmap, gBitmap_nativeInstanceID); 305 SkASSERT(b); 306 return b; 307} 308 309SkBitmap::Config GraphicsJNI::getNativeBitmapConfig(JNIEnv* env, 310 jobject jconfig) { 311 SkASSERT(env); 312 if (NULL == jconfig) { 313 return SkBitmap::kNo_Config; 314 } 315 SkASSERT(env->IsInstanceOf(jconfig, gBitmapConfig_class)); 316 int c = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID); 317 if (c < 0 || c >= SkBitmap::kConfigCount) { 318 c = SkBitmap::kNo_Config; 319 } 320 return static_cast<SkBitmap::Config>(c); 321} 322 323SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) { 324 SkASSERT(env); 325 SkASSERT(canvas); 326 SkASSERT(env->IsInstanceOf(canvas, gCanvas_class)); 327 SkCanvas* c = (SkCanvas*)env->GetIntField(canvas, gCanvas_nativeInstanceID); 328 SkASSERT(c); 329 return c; 330} 331 332SkPaint* GraphicsJNI::getNativePaint(JNIEnv* env, jobject paint) { 333 SkASSERT(env); 334 SkASSERT(paint); 335 SkASSERT(env->IsInstanceOf(paint, gPaint_class)); 336 SkPaint* p = (SkPaint*)env->GetIntField(paint, gPaint_nativeInstanceID); 337 SkASSERT(p); 338 return p; 339} 340 341SkPicture* GraphicsJNI::getNativePicture(JNIEnv* env, jobject picture) 342{ 343 SkASSERT(env); 344 SkASSERT(picture); 345 SkASSERT(env->IsInstanceOf(picture, gPicture_class)); 346 SkPicture* p = (SkPicture*)env->GetIntField(picture, gPicture_nativeInstanceID); 347 SkASSERT(p); 348 return p; 349} 350 351SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region) 352{ 353 SkASSERT(env); 354 SkASSERT(region); 355 SkASSERT(env->IsInstanceOf(region, gRegion_class)); 356 SkRegion* r = (SkRegion*)env->GetIntField(region, gRegion_nativeInstanceID); 357 SkASSERT(r); 358 return r; 359} 360 361/////////////////////////////////////////////////////////////////////////////////////////// 362 363jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable, 364 jbyteArray ninepatch, int density) 365{ 366 SkASSERT(bitmap != NULL); 367 SkASSERT(NULL != bitmap->pixelRef()); 368 369 jobject obj = env->AllocObject(gBitmap_class); 370 if (obj) { 371 env->CallVoidMethod(obj, gBitmap_constructorMethodID, 372 (jint)bitmap, isMutable, ninepatch, density); 373 if (hasException(env)) { 374 obj = NULL; 375 } 376 } 377 return obj; 378} 379jobject GraphicsJNI::createLargeBitmap(JNIEnv* env, SkLargeBitmap* bitmap) 380{ 381 SkASSERT(bitmap != NULL); 382 383 jobject obj = env->AllocObject(gLargeBitmap_class); 384 if (hasException(env)) { 385 obj = NULL; 386 return obj; 387 } 388 if (obj) { 389 env->CallVoidMethod(obj, gLargeBitmap_constructorMethodID, (jint)bitmap); 390 if (hasException(env)) { 391 obj = NULL; 392 } 393 } 394 return obj; 395} 396 397jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region) 398{ 399 SkASSERT(region != NULL); 400 jobject obj = env->AllocObject(gRegion_class); 401 if (obj) { 402 env->CallVoidMethod(obj, gRegion_constructorMethodID, (jint)region, 0); 403 if (hasException(env)) { 404 obj = NULL; 405 } 406 } 407 return obj; 408} 409 410#include "SkPixelRef.h" 411 412static JNIEnv* vm2env(JavaVM* vm) 413{ 414 JNIEnv* env = NULL; 415 if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK || NULL == env) 416 { 417 SkDebugf("------- [%p] vm->GetEnv() failed\n", vm); 418 sk_throw(); 419 } 420 return env; 421} 422 423#ifdef TRACK_LOCK_COUNT 424 static int gLockCount; 425#endif 426 427/////////////////////////////////////////////////////////////////////////////// 428 429#include "SkMallocPixelRef.h" 430 431/* Extend SkMallocPixelRef to inform the VM when we free up the storage 432*/ 433class AndroidPixelRef : public SkMallocPixelRef { 434public: 435 /** Allocate the specified buffer for pixels. The memory is freed when the 436 last owner of this pixelref is gone. Our caller has already informed 437 the VM of our allocation. 438 */ 439 AndroidPixelRef(JNIEnv* env, void* storage, size_t size, 440 SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable) { 441 SkASSERT(storage); 442 SkASSERT(env); 443 444 if (env->GetJavaVM(&fVM) != JNI_OK) { 445 SkDebugf("------ [%p] env->GetJavaVM failed\n", env); 446 sk_throw(); 447 } 448 } 449 450 virtual ~AndroidPixelRef() { 451 JNIEnv* env = vm2env(fVM); 452// SkDebugf("-------------- inform VM we're releasing %d bytes\n", this->getSize()); 453 jlong jsize = this->getSize(); // the VM wants longs for the size 454 env->CallVoidMethod(gVMRuntime_singleton, 455 gVMRuntime_trackExternalFreeMethodID, 456 jsize); 457 if (GraphicsJNI::hasException(env)) { 458 env->ExceptionClear(); 459 } 460 } 461 462private: 463 JavaVM* fVM; 464}; 465 466bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, 467 SkColorTable* ctable, bool reportSizeToVM) { 468 Sk64 size64 = bitmap->getSize64(); 469 if (size64.isNeg() || !size64.is32()) { 470 doThrow(env, "java/lang/IllegalArgumentException", 471 "bitmap size exceeds 32bits"); 472 return false; 473 } 474 475 size_t size = size64.get32(); 476 jlong jsize = size; // the VM wants longs for the size 477 if (reportSizeToVM) { 478 // SkDebugf("-------------- inform VM we've allocated %d bytes\n", size); 479 bool r = env->CallBooleanMethod(gVMRuntime_singleton, 480 gVMRuntime_trackExternalAllocationMethodID, 481 jsize); 482 if (GraphicsJNI::hasException(env)) { 483 return false; 484 } 485 if (!r) { 486 LOGE("VM won't let us allocate %zd bytes\n", size); 487 doThrowOOME(env, "bitmap size exceeds VM budget"); 488 return false; 489 } 490 } 491 // call the version of malloc that returns null on failure 492 void* addr = sk_malloc_flags(size, 0); 493 if (NULL == addr) { 494 if (reportSizeToVM) { 495 // SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size); 496 // we didn't actually allocate it, so inform the VM 497 env->CallVoidMethod(gVMRuntime_singleton, 498 gVMRuntime_trackExternalFreeMethodID, 499 jsize); 500 if (!GraphicsJNI::hasException(env)) { 501 doThrowOOME(env, "bitmap size too large for malloc"); 502 } 503 } 504 return false; 505 } 506 507 SkPixelRef* pr = reportSizeToVM ? 508 new AndroidPixelRef(env, addr, size, ctable) : 509 new SkMallocPixelRef(addr, size, ctable); 510 bitmap->setPixelRef(pr)->unref(); 511 // since we're already allocated, we lockPixels right away 512 // HeapAllocator behaves this way too 513 bitmap->lockPixels(); 514 return true; 515} 516 517/////////////////////////////////////////////////////////////////////////////// 518 519JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM) 520 : fReportSizeToVM(reportSizeToVM) { 521 if (env->GetJavaVM(&fVM) != JNI_OK) { 522 SkDebugf("------ [%p] env->GetJavaVM failed\n", env); 523 sk_throw(); 524 } 525} 526 527bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) { 528 JNIEnv* env = vm2env(fVM); 529 return GraphicsJNI::setJavaPixelRef(env, bitmap, ctable, fReportSizeToVM); 530} 531 532//////////////////////////////////////////////////////////////////////////////// 533 534JavaMemoryUsageReporter::JavaMemoryUsageReporter(JNIEnv* env) 535 : fTotalSize(0) { 536 if (env->GetJavaVM(&fVM) != JNI_OK) { 537 SkDebugf("------ [%p] env->GetJavaVM failed\n", env); 538 sk_throw(); 539 } 540} 541 542JavaMemoryUsageReporter::~JavaMemoryUsageReporter() { 543 JNIEnv* env = vm2env(fVM); 544 jlong jtotalSize = fTotalSize; 545 env->CallVoidMethod(gVMRuntime_singleton, 546 gVMRuntime_trackExternalFreeMethodID, 547 jtotalSize); 548} 549 550bool JavaMemoryUsageReporter::reportMemory(size_t memorySize) { 551 jlong jsize = memorySize; // the VM wants longs for the size 552 JNIEnv* env = vm2env(fVM); 553 bool r = env->CallBooleanMethod(gVMRuntime_singleton, 554 gVMRuntime_trackExternalAllocationMethodID, 555 jsize); 556 if (GraphicsJNI::hasException(env)) { 557 return false; 558 } 559 if (!r) { 560 LOGE("VM won't let us allocate %zd bytes\n", memorySize); 561 doThrowOOME(env, "bitmap size exceeds VM budget"); 562 return false; 563 } 564 fTotalSize += memorySize; 565 return true; 566} 567 568//////////////////////////////////////////////////////////////////////////////// 569 570static jclass make_globalref(JNIEnv* env, const char classname[]) 571{ 572 jclass c = env->FindClass(classname); 573 SkASSERT(c); 574 return (jclass)env->NewGlobalRef(c); 575} 576 577static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, 578 const char fieldname[], const char type[]) 579{ 580 jfieldID id = env->GetFieldID(clazz, fieldname, type); 581 SkASSERT(id); 582 return id; 583} 584 585int register_android_graphics_Graphics(JNIEnv* env) 586{ 587 jmethodID m; 588 jclass c; 589 590 gRect_class = make_globalref(env, "android/graphics/Rect"); 591 gRect_leftFieldID = getFieldIDCheck(env, gRect_class, "left", "I"); 592 gRect_topFieldID = getFieldIDCheck(env, gRect_class, "top", "I"); 593 gRect_rightFieldID = getFieldIDCheck(env, gRect_class, "right", "I"); 594 gRect_bottomFieldID = getFieldIDCheck(env, gRect_class, "bottom", "I"); 595 596 gRectF_class = make_globalref(env, "android/graphics/RectF"); 597 gRectF_leftFieldID = getFieldIDCheck(env, gRectF_class, "left", "F"); 598 gRectF_topFieldID = getFieldIDCheck(env, gRectF_class, "top", "F"); 599 gRectF_rightFieldID = getFieldIDCheck(env, gRectF_class, "right", "F"); 600 gRectF_bottomFieldID = getFieldIDCheck(env, gRectF_class, "bottom", "F"); 601 602 gPoint_class = make_globalref(env, "android/graphics/Point"); 603 gPoint_xFieldID = getFieldIDCheck(env, gPoint_class, "x", "I"); 604 gPoint_yFieldID = getFieldIDCheck(env, gPoint_class, "y", "I"); 605 606 gPointF_class = make_globalref(env, "android/graphics/PointF"); 607 gPointF_xFieldID = getFieldIDCheck(env, gPointF_class, "x", "F"); 608 gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F"); 609 610 gBitmap_class = make_globalref(env, "android/graphics/Bitmap"); 611 gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I"); 612 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", 613 "(IZ[BI)V"); 614 615 gLargeBitmap_class = make_globalref(env, "android/graphics/LargeBitmap"); 616 gLargeBitmap_constructorMethodID = env->GetMethodID(gLargeBitmap_class, "<init>", "(I)V"); 617 618 gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config"); 619 gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class, 620 "nativeInt", "I"); 621 622 gCanvas_class = make_globalref(env, "android/graphics/Canvas"); 623 gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvas", "I"); 624 625 gPaint_class = make_globalref(env, "android/graphics/Paint"); 626 gPaint_nativeInstanceID = getFieldIDCheck(env, gPaint_class, "mNativePaint", "I"); 627 628 gPicture_class = make_globalref(env, "android/graphics/Picture"); 629 gPicture_nativeInstanceID = getFieldIDCheck(env, gPicture_class, "mNativePicture", "I"); 630 631 gRegion_class = make_globalref(env, "android/graphics/Region"); 632 gRegion_nativeInstanceID = getFieldIDCheck(env, gRegion_class, "mNativeRegion", "I"); 633 gRegion_constructorMethodID = env->GetMethodID(gRegion_class, "<init>", 634 "(II)V"); 635 636 // Get the VMRuntime class. 637 c = env->FindClass("dalvik/system/VMRuntime"); 638 SkASSERT(c); 639 // Look up VMRuntime.getRuntime(). 640 m = env->GetStaticMethodID(c, "getRuntime", "()Ldalvik/system/VMRuntime;"); 641 SkASSERT(m); 642 // Call VMRuntime.getRuntime() and hold onto its result. 643 gVMRuntime_singleton = env->CallStaticObjectMethod(c, m); 644 SkASSERT(gVMRuntime_singleton); 645 gVMRuntime_singleton = (jobject)env->NewGlobalRef(gVMRuntime_singleton); 646 // Look up the VMRuntime methods we'll be using. 647 gVMRuntime_trackExternalAllocationMethodID = 648 env->GetMethodID(c, "trackExternalAllocation", "(J)Z"); 649 gVMRuntime_trackExternalFreeMethodID = 650 env->GetMethodID(c, "trackExternalFree", "(J)V"); 651 652 return 0; 653} 654 655