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 12 void 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 24 void doThrowNPE(JNIEnv* env) { 25 doThrow(env, "java/lang/NullPointerException"); 26 } 27 28 void doThrowAIOOBE(JNIEnv* env) { 29 doThrow(env, "java/lang/ArrayIndexOutOfBoundsException"); 30 } 31 32 void doThrowRE(JNIEnv* env, const char* msg) { 33 doThrow(env, "java/lang/RuntimeException", msg); 34 } 35 36 void doThrowIAE(JNIEnv* env, const char* msg) { 37 doThrow(env, "java/lang/IllegalArgumentException", msg); 38 } 39 40 void doThrowISE(JNIEnv* env, const char* msg) { 41 doThrow(env, "java/lang/IllegalStateException", msg); 42 } 43 44 void doThrowOOME(JNIEnv* env, const char* msg) { 45 doThrow(env, "java/lang/OutOfMemoryError", msg); 46 } 47 48 void doThrowIOE(JNIEnv* env, const char* msg) { 49 doThrow(env, "java/lang/IOException", msg); 50 } 51 52 bool 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 63 AutoJavaFloatArray::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 77 AutoJavaFloatArray::~AutoJavaFloatArray() { 78 if (fPtr) { 79 fEnv->ReleaseFloatArrayElements(fArray, fPtr, fReleaseMode); 80 } 81 } 82 83 AutoJavaIntArray::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 96 AutoJavaIntArray::~AutoJavaIntArray() { 97 if (fPtr) { 98 fEnv->ReleaseIntArrayElements(fArray, fPtr, 0); 99 } 100 } 101 102 AutoJavaShortArray::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 116 AutoJavaShortArray::~AutoJavaShortArray() { 117 if (fPtr) { 118 fEnv->ReleaseShortArrayElements(fArray, fPtr, fReleaseMode); 119 } 120 } 121 122 AutoJavaByteArray::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 135 AutoJavaByteArray::~AutoJavaByteArray() { 136 if (fPtr) { 137 fEnv->ReleaseByteArrayElements(fArray, fPtr, 0); 138 } 139 } 140 141 /////////////////////////////////////////////////////////////////////////////// 142 143 static jclass gRect_class; 144 static jfieldID gRect_leftFieldID; 145 static jfieldID gRect_topFieldID; 146 static jfieldID gRect_rightFieldID; 147 static jfieldID gRect_bottomFieldID; 148 149 static jclass gRectF_class; 150 static jfieldID gRectF_leftFieldID; 151 static jfieldID gRectF_topFieldID; 152 static jfieldID gRectF_rightFieldID; 153 static jfieldID gRectF_bottomFieldID; 154 155 static jclass gPoint_class; 156 static jfieldID gPoint_xFieldID; 157 static jfieldID gPoint_yFieldID; 158 159 static jclass gPointF_class; 160 static jfieldID gPointF_xFieldID; 161 static jfieldID gPointF_yFieldID; 162 163 static jclass gBitmap_class; 164 static jfieldID gBitmap_nativeInstanceID; 165 static jmethodID gBitmap_constructorMethodID; 166 static jmethodID gBitmap_allocBufferMethodID; 167 168 static jclass gBitmapConfig_class; 169 static jfieldID gBitmapConfig_nativeInstanceID; 170 171 static jclass gCanvas_class; 172 static jfieldID gCanvas_nativeInstanceID; 173 174 static jclass gPaint_class; 175 static jfieldID gPaint_nativeInstanceID; 176 177 static jclass gPicture_class; 178 static jfieldID gPicture_nativeInstanceID; 179 180 static jclass gRegion_class; 181 static jfieldID gRegion_nativeInstanceID; 182 static jmethodID gRegion_constructorMethodID; 183 184 static jobject gVMRuntime_singleton; 185 static jmethodID gVMRuntime_trackExternalAllocationMethodID; 186 static jmethodID gVMRuntime_trackExternalFreeMethodID; 187 188 /////////////////////////////////////////////////////////////////////////////// 189 190 void 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 200 void 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 210 SkIRect* 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 221 void 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 231 SkRect* 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 242 SkRect* 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 253 void 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 263 SkIPoint* 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 272 void 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 280 SkPoint* 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 289 void 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 297 SkBitmap* 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 306 SkBitmap::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 320 SkCanvas* 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 329 SkPaint* 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 338 SkPicture* 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 348 SkRegion* 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 360 jobject 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 377 jobject 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 392 static 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 */ 413 class AndroidPixelRef : public SkMallocPixelRef { 414 public: 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 442 private: 443 JavaVM* fVM; 444 }; 445 446 bool 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 499 JavaPixelAllocator::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 507 bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) { 508 JNIEnv* env = vm2env(fVM); 509 return GraphicsJNI::setJavaPixelRef(env, bitmap, ctable, fReportSizeToVM); 510 } 511 512 //////////////////////////////////////////////////////////////////////////////// 513 514 JavaMemoryUsageReporter::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 522 JavaMemoryUsageReporter::~JavaMemoryUsageReporter() { 523 JNIEnv* env = vm2env(fVM); 524 jlong jtotalSize = fTotalSize; 525 env->CallVoidMethod(gVMRuntime_singleton, 526 gVMRuntime_trackExternalFreeMethodID, 527 jtotalSize); 528 } 529 530 bool 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 550 static 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 557 static 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 565 int 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