More JNI exception-throwing cleanup.

There are a few (unimportant) bug fixes here. There were several attempts to
throw exceptions in situations where there's already a pending exception.

There were also cases where the code was wrong; it was checking for a NULL
return from Get*ArrayElements and throwing NPE, but passing NULL is an error
that causes a crash and a NULL return means an exception has already been
thrown. I didn't want to get into the Scoped* classes just yet, but that
was by far the easiest way to fix this.

Change-Id: I0b31160ee51b96e82539f6514b8412b149dba7c3
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 54b7fbb..f8f8761 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -176,7 +176,8 @@
 	external/icu4c/common \
 	external/jpeg \
 	external/harfbuzz/src \
-	frameworks/opt/emoji
+	frameworks/opt/emoji \
+	libcore/include
 
 LOCAL_SHARED_LIBRARIES := \
 	libexpat \
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 233167f..6c28e65 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -11,7 +11,7 @@
 #include <android_runtime/AndroidRuntime.h>
 
 void doThrowNPE(JNIEnv* env) {
-    jniThrowException(env, "java/lang/NullPointerException", NULL);
+    jniThrowNullPointerException(env, NULL);
 }
 
 void doThrowAIOOBE(JNIEnv* env) {
@@ -19,7 +19,7 @@
 }
 
 void doThrowRE(JNIEnv* env, const char* msg) {
-    jniThrowException(env, "java/lang/RuntimeException", msg);
+    jniThrowRuntimeException(env, msg);
 }
 
 void doThrowIAE(JNIEnv* env, const char* msg) {
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 50df0f7..f9a3518 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -30,7 +30,7 @@
 extern void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
                 const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
                            const SkPaint* paint, SkRegion** outRegion);
-    
+
 using namespace android;
 
 class SkNinePatchGlue {
@@ -58,8 +58,7 @@
     static void validateNinePatchChunk(JNIEnv* env, jobject, jint, jbyteArray obj)
     {
         if (env->GetArrayLength(obj) < (int) (sizeof(Res_png_9patch))) {
-            jniThrowException(env, "java/lang/RuntimeException",
-                              "Array too small for chunk.");
+            jniThrowRuntimeException(env, "Array too small for chunk.");
             return;
         }
 
@@ -80,7 +79,7 @@
             assert(chunkSize == chunk->serializedSize());
             // this relies on deserialization being done in place
             Res_png_9patch::deserialize(chunk);
-            
+
             if (destDensity == srcDensity || destDensity == 0
                     || srcDensity == 0) {
                 LOGV("Drawing unscaled 9-patch: (%g,%g)-(%g,%g)",
@@ -89,26 +88,26 @@
                 NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
             } else {
                 canvas->save();
-                
+
                 SkScalar scale = SkFloatToScalar(destDensity / (float)srcDensity);
                 canvas->translate(bounds.fLeft, bounds.fTop);
                 canvas->scale(scale, scale);
-    
+
                 bounds.fRight = SkScalarDiv(bounds.fRight-bounds.fLeft, scale);
                 bounds.fBottom = SkScalarDiv(bounds.fBottom-bounds.fTop, scale);
                 bounds.fLeft = bounds.fTop = 0;
-    
+
                 LOGV("Drawing scaled 9-patch: (%g,%g)-(%g,%g) srcDensity=%d destDensity=%d",
                         SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
                         SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom),
                         srcDensity, destDensity);
-                
+
                 NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
-    
+
                 canvas->restore();
             }
         }
-    } 
+    }
 
     static void drawF(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRectF,
                       const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
@@ -125,7 +124,7 @@
 
         draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
     }
- 
+
     static void drawI(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRect,
                       const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
                       jint destDensity, jint srcDensity)
@@ -140,7 +139,7 @@
         GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
         draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
     }
-    
+
     static jint getTransparentRegion(JNIEnv* env, jobject,
                     const SkBitmap* bitmap, jbyteArray chunkObj,
                     jobject boundsRect)
@@ -148,7 +147,7 @@
         SkASSERT(bitmap);
         SkASSERT(chunkObj);
         SkASSERT(boundsRect);
-        
+
         SkRect      bounds;
         GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
         size_t chunkSize = env->GetArrayLength(chunkObj);
@@ -179,7 +178,7 @@
     { "validateNinePatchChunk", "(I[B)V",               (void*)SkNinePatchGlue::validateNinePatchChunk   },
     { "nativeDraw", "(ILandroid/graphics/RectF;I[BIII)V", (void*)SkNinePatchGlue::drawF   },
     { "nativeDraw", "(ILandroid/graphics/Rect;I[BIII)V",  (void*)SkNinePatchGlue::drawI   },
-    { "nativeGetTransparentRegion", "(I[BLandroid/graphics/Rect;)I", 
+    { "nativeGetTransparentRegion", "(I[BLandroid/graphics/Rect;)I",
                                                         (void*)SkNinePatchGlue::getTransparentRegion   }
 };
 
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index bfbfd37..97580f54 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -105,7 +105,7 @@
     }
     LOGV("get_native_camera: context=%p, camera=%p", context, camera.get());
     if (camera == 0) {
-        jniThrowException(env, "java/lang/RuntimeException", "Method called after release()");
+        jniThrowRuntimeException(env, "Method called after release()");
     }
 
     if (pContext != NULL) *pContext = context;
@@ -232,8 +232,7 @@
                         break;
                     }
                     default: {
-                        jniThrowException(env,
-                            "java/lang/RuntimeException", "Unsupported message type");
+                        jniThrowRuntimeException(env, "Unsupported message type");
                         return;
                     }
                 }
@@ -391,8 +390,7 @@
     CameraInfo cameraInfo;
     status_t rc = Camera::getCameraInfo(cameraId, &cameraInfo);
     if (rc != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException",
-                          "Fail to get camera info");
+        jniThrowRuntimeException(env, "Fail to get camera info");
         return;
     }
     env->SetIntField(info_obj, fields.facing, cameraInfo.facing);
@@ -406,20 +404,19 @@
     sp<Camera> camera = Camera::connect(cameraId);
 
     if (camera == NULL) {
-        jniThrowException(env, "java/lang/RuntimeException",
-                          "Fail to connect to camera service");
+        jniThrowRuntimeException(env, "Fail to connect to camera service");
         return;
     }
 
     // make sure camera hardware is alive
     if (camera->getStatus() != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "Camera initialization failed");
+        jniThrowRuntimeException(env, "Camera initialization failed");
         return;
     }
 
     jclass clazz = env->GetObjectClass(thiz);
     if (clazz == NULL) {
-        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/hardware/Camera");
+        jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
         return;
     }
 
@@ -508,7 +505,7 @@
     if (camera == 0) return;
 
     if (camera->startPreview() != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "startPreview failed");
+        jniThrowRuntimeException(env, "startPreview failed");
         return;
     }
 }
@@ -564,7 +561,7 @@
     if (c == 0) return;
 
     if (c->autoFocus() != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "autoFocus failed");
+        jniThrowRuntimeException(env, "autoFocus failed");
     }
 }
 
@@ -576,7 +573,7 @@
     if (c == 0) return;
 
     if (c->cancelAutoFocus() != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "cancelAutoFocus failed");
+        jniThrowRuntimeException(env, "cancelAutoFocus failed");
     }
 }
 
@@ -606,7 +603,7 @@
     }
 
     if (camera->takePicture(msgType) != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "takePicture failed");
+        jniThrowRuntimeException(env, "takePicture failed");
         return;
     }
 }
@@ -624,7 +621,7 @@
         env->ReleaseStringCritical(params, str);
     }
     if (camera->setParameters(params8) != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "setParameters failed");
+        jniThrowRuntimeException(env, "setParameters failed");
         return;
     }
 }
@@ -657,7 +654,7 @@
     if (camera == 0) return;
 
     if (camera->lock() != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "lock failed");
+        jniThrowRuntimeException(env, "lock failed");
     }
 }
 
@@ -668,7 +665,7 @@
     if (camera == 0) return;
 
     if (camera->unlock() != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "unlock failed");
+        jniThrowRuntimeException(env, "unlock failed");
     }
 }
 
@@ -684,7 +681,7 @@
         sprintf(msg, "invalid zoom value=%d", value);
         jniThrowException(env, "java/lang/IllegalArgumentException", msg);
     } else if (rc != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "start smooth zoom failed");
+        jniThrowRuntimeException(env, "start smooth zoom failed");
     }
 }
 
@@ -695,7 +692,7 @@
     if (camera == 0) return;
 
     if (camera->sendCommand(CAMERA_CMD_STOP_SMOOTH_ZOOM, 0, 0) != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "stop smooth zoom failed");
+        jniThrowRuntimeException(env, "stop smooth zoom failed");
     }
 }
 
@@ -707,7 +704,7 @@
     if (camera == 0) return;
 
     if (camera->sendCommand(CAMERA_CMD_SET_DISPLAY_ORIENTATION, value, 0) != NO_ERROR) {
-        jniThrowException(env, "java/lang/RuntimeException", "set display orientation failed");
+        jniThrowRuntimeException(env, "set display orientation failed");
     }
 }
 
diff --git a/core/jni/android_media_JetPlayer.cpp b/core/jni/android_media_JetPlayer.cpp
index 3727f4b..a7ffff4 100644
--- a/core/jni/android_media_JetPlayer.cpp
+++ b/core/jni/android_media_JetPlayer.cpp
@@ -85,7 +85,7 @@
     EAS_RESULT result = lpJet->init();
 
     if(result==EAS_SUCCESS) {
-        // save our newly created C++ JetPlayer in the "nativePlayerInJavaObj" field 
+        // save our newly created C++ JetPlayer in the "nativePlayerInJavaObj" field
         // of the Java object (in mNativePlayerInJavaObj)
         env->SetIntField(thiz, javaJetPlayerFields.nativePlayerInJavaObj, (int)lpJet);
         return JNI_TRUE;
@@ -120,7 +120,7 @@
 {
     android_media_JetPlayer_finalize(env, thiz);
     env->SetIntField(thiz, javaJetPlayerFields.nativePlayerInJavaObj, 0);
-    LOGV("android_media_JetPlayer_release() done");   
+    LOGV("android_media_JetPlayer_release() done");
 }
 
 
@@ -134,14 +134,13 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for openFile()");
     }
-    
+
     // set up event callback function
     lpJet->setEventCallback(jetPlayerEventCallback);
 
     const char *pathStr = env->GetStringUTFChars(path, NULL);
     if (pathStr == NULL) {  // Out of memory
         LOGE("android_media_JetPlayer_openFile(): aborting, out of memory");
-        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
         return JNI_FALSE;
     }
 
@@ -171,14 +170,14 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for openFile()");
     }
-    
+
     // set up event callback function
     lpJet->setEventCallback(jetPlayerEventCallback);
-    
+
     LOGV("android_media_JetPlayer_openFileDescr(): trying to load JET file through its fd" );
     EAS_RESULT result = lpJet->loadFromFD(getParcelFileDescriptorFD(env, fileDescriptor),
         (long long)offset, (long long)length); // cast params to types used by EAS_FILE
-    
+
     if(result==EAS_SUCCESS) {
         LOGV("android_media_JetPlayer_openFileDescr(): file successfully opened");
         return JNI_TRUE;
@@ -200,7 +199,7 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for closeFile()");
     }
-    
+
     if( lpJet->closeFile()==EAS_SUCCESS) {
         //LOGV("android_media_JetPlayer_closeFile(): file successfully closed");
         return JNI_TRUE;
@@ -221,13 +220,13 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for play()");
     }
-    
+
     EAS_RESULT result = lpJet->play();
     if( result==EAS_SUCCESS) {
         //LOGV("android_media_JetPlayer_play(): play successful");
         return JNI_TRUE;
     } else {
-        LOGE("android_media_JetPlayer_play(): failed to play with EAS error code %ld", 
+        LOGE("android_media_JetPlayer_play(): failed to play with EAS error code %ld",
             result);
         return JNI_FALSE;
     }
@@ -244,7 +243,7 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for pause()");
     }
-    
+
     EAS_RESULT result = lpJet->pause();
     if( result==EAS_SUCCESS) {
         //LOGV("android_media_JetPlayer_pause(): pause successful");
@@ -273,7 +272,7 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for queueSegment()");
     }
-    
+
     EAS_RESULT result
         = lpJet->queueSegment(segmentNum, libNum, repeatCount, transpose, muteFlags, userID);
     if(result==EAS_SUCCESS) {
@@ -299,7 +298,7 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for queueSegmentMuteArray()");
     }
-    
+
     EAS_RESULT result=EAS_FAILURE;
 
     jboolean *muteTracks = NULL;
@@ -326,7 +325,7 @@
         //LOGV("android_media_JetPlayer_queueSegmentMuteArray(): segment successfully queued");
         return JNI_TRUE;
     } else {
-        LOGE("android_media_JetPlayer_queueSegmentMuteArray(): failed with EAS error code %ld", 
+        LOGE("android_media_JetPlayer_queueSegmentMuteArray(): failed with EAS error code %ld",
             result);
         return JNI_FALSE;
     }
@@ -344,7 +343,7 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for setMuteFlags()");
     }
-    
+
     EAS_RESULT result;
     result = lpJet->setMuteFlags(muteFlags, bSync==JNI_TRUE ? true : false);
     if(result==EAS_SUCCESS) {
@@ -368,7 +367,7 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for setMuteArray()");
     }
-    
+
     EAS_RESULT result=EAS_FAILURE;
 
     jboolean *muteTracks = NULL;
@@ -413,9 +412,9 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for setMuteFlag()");
     }
-    
+
     EAS_RESULT result;
-    result = lpJet->setMuteFlag(trackId, 
+    result = lpJet->setMuteFlag(trackId,
         muteFlag==JNI_TRUE ? true : false, bSync==JNI_TRUE ? true : false);
     if(result==EAS_SUCCESS) {
         //LOGV("android_media_JetPlayer_setMuteFlag(): mute flag successfully updated for track %d", trackId);
@@ -438,7 +437,7 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for triggerClip()");
     }
-    
+
     EAS_RESULT result;
     result = lpJet->triggerClip(clipId);
     if(result==EAS_SUCCESS) {
@@ -462,7 +461,7 @@
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve JetPlayer pointer for clearQueue()");
     }
-    
+
     EAS_RESULT result = lpJet->clearQueue();
     if(result==EAS_SUCCESS) {
         //LOGV("android_media_JetPlayer_clearQueue(): clearQueue successful");
@@ -482,16 +481,16 @@
     {"native_setup",       "(Ljava/lang/Object;II)Z", (void *)android_media_JetPlayer_setup},
     {"native_finalize",    "()V",                   (void *)android_media_JetPlayer_finalize},
     {"native_release",     "()V",                   (void *)android_media_JetPlayer_release},
-    {"native_loadJetFromFile", 
+    {"native_loadJetFromFile",
                            "(Ljava/lang/String;)Z", (void *)android_media_JetPlayer_loadFromFile},
     {"native_loadJetFromFileD", "(Ljava/io/FileDescriptor;JJ)Z",
                                                     (void *)android_media_JetPlayer_loadFromFileD},
     {"native_closeJetFile","()Z",                   (void *)android_media_JetPlayer_closeFile},
     {"native_playJet",     "()Z",                   (void *)android_media_JetPlayer_play},
     {"native_pauseJet",    "()Z",                   (void *)android_media_JetPlayer_pause},
-    {"native_queueJetSegment",  
+    {"native_queueJetSegment",
                            "(IIIIIB)Z",             (void *)android_media_JetPlayer_queueSegment},
-    {"native_queueJetSegmentMuteArray", 
+    {"native_queueJetSegmentMuteArray",
                            "(IIII[ZB)Z",     (void *)android_media_JetPlayer_queueSegmentMuteArray},
     {"native_setMuteFlags","(IZ)Z",                 (void *)android_media_JetPlayer_setMuteFlags},
     {"native_setMuteArray","([ZZ)Z",                (void *)android_media_JetPlayer_setMuteArray},
@@ -510,7 +509,7 @@
     javaJetPlayerFields.jetClass = NULL;
     javaJetPlayerFields.postNativeEventInJava = NULL;
     javaJetPlayerFields.nativePlayerInJavaObj = NULL;
-    
+
     // Get the JetPlayer java class
     jetPlayerClass = env->FindClass(kClassPathName);
     if (jetPlayerClass == NULL) {
diff --git a/core/jni/android_media_ToneGenerator.cpp b/core/jni/android_media_ToneGenerator.cpp
index 50aa967..fdd586b 100644
--- a/core/jni/android_media_ToneGenerator.cpp
+++ b/core/jni/android_media_ToneGenerator.cpp
@@ -44,7 +44,7 @@
     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetIntField(thiz,
             fields.context);
     if (lpToneGen == NULL) {
-        jniThrowException(env, "java/lang/RuntimeException", "Method called after release()");
+        jniThrowRuntimeException(env, "Method called after release()");
         return false;
     }
 
@@ -59,7 +59,7 @@
 
     LOGV("ToneGenerator lpToneGen: %x\n", (unsigned int)lpToneGen);
     if (lpToneGen == NULL) {
-        jniThrowException(env, "java/lang/RuntimeException", "Method called after release()");
+        jniThrowRuntimeException(env, "Method called after release()");
         return;
     }
     lpToneGen->stopTone();
@@ -94,7 +94,7 @@
 
     if (!lpToneGen->isInited()) {
         LOGE("ToneGenerator init failed \n");
-        jniThrowException(env, "java/lang/RuntimeException", "Init failed");
+        jniThrowRuntimeException(env, "Init failed");
         return;
     }
 
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index e58794b..c8add70 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -99,9 +99,9 @@
 
 #define DEFAULT_BACKLOG 4
 
-/* private native void bindLocal(FileDescriptor fd, String name, namespace) 
- * throws IOException; 
- */ 
+/* private native void bindLocal(FileDescriptor fd, String name, namespace)
+ * throws IOException;
+ */
 
 static void
 socket_bind_local (JNIEnv *env, jobject object, jobject fileDescriptor,
@@ -113,7 +113,7 @@
 
 
     if (name == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
     }
 
     fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
@@ -127,7 +127,7 @@
     ret = socket_local_server_bind(fd, nameUtf8, namespaceId);
 
     env->ReleaseStringUTFChars(name, nameUtf8);
- 
+
     if (ret < 0) {
         jniThrowIOException(env, errno);
         return;
@@ -166,14 +166,14 @@
         struct sockaddr address;
         struct sockaddr_un un_address;
     } sa;
-    
+
     int ret;
     int retFD;
     int fd;
     socklen_t addrlen;
 
     if (s == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return NULL;
     }
 
@@ -345,7 +345,7 @@
             struct timeval timeout;
             timeout.tv_sec = intValue / 1000;
             timeout.tv_usec = (intValue % 1000) * 1000;
-            
+
             ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
                     (void *)&timeout, sizeof(timeout));
 
@@ -353,7 +353,7 @@
                 ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
                         (void *)&timeout, sizeof(timeout));
             }
-            
+
             break;
         }
         default: {
@@ -372,7 +372,7 @@
     }
 }
 
-static jint socket_available (JNIEnv *env, jobject object, 
+static jint socket_available (JNIEnv *env, jobject object,
         jobject fileDescriptor)
 {
     int fd;
@@ -398,7 +398,7 @@
     return (jint)avail;
 #else
 // there appears to be a bionic bug that prevents this version from working.
-    
+
     ssize_t ret;
     struct msghdr msg;
 
@@ -408,7 +408,7 @@
         ret = recvmsg(fd, &msg, MSG_PEEK | MSG_DONTWAIT | MSG_NOSIGNAL);
     } while (ret < 0 && errno == EINTR);
 
-    
+
     // MSG_PEEK returns 0 on EOF and EWOULDBLOCK on none available
     if (ret < 0 && errno == EWOULDBLOCK) {
         return 0;
@@ -427,7 +427,7 @@
     int err;
 
     if (fileDescriptor == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
 
@@ -448,7 +448,7 @@
 }
 
 /**
- * Processes ancillary data, handling only 
+ * Processes ancillary data, handling only
  * SCM_RIGHTS. Creates appropriate objects and sets appropriate
  * fields in the LocalSocketImpl object. Returns 0 on success
  * or -1 if an exception was thrown.
@@ -457,7 +457,7 @@
 {
     struct cmsghdr *cmsgptr;
 
-    for (cmsgptr = CMSG_FIRSTHDR(pMsg); 
+    for (cmsgptr = CMSG_FIRSTHDR(pMsg);
             cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(pMsg, cmsgptr)) {
 
         if (cmsgptr->cmsg_level != SOL_SOCKET) {
@@ -467,11 +467,11 @@
         if (cmsgptr->cmsg_type == SCM_RIGHTS) {
             int *pDescriptors = (int *)CMSG_DATA(cmsgptr);
             jobjectArray fdArray;
-            int count 
+            int count
                 = ((cmsgptr->cmsg_len - CMSG_LEN(0)) / sizeof(int));
 
             if (count < 0) {
-                jniThrowException(env, "java/io/IOException", 
+                jniThrowException(env, "java/io/IOException",
                     "invalid cmsg length");
             }
 
@@ -482,7 +482,7 @@
             }
 
             for (int i = 0; i < count; i++) {
-                jobject fdObject 
+                jobject fdObject
                         = jniCreateFileDescriptor(env, pDescriptors[i]);
 
                 if (env->ExceptionOccurred() != NULL) {
@@ -514,7 +514,7 @@
  * Returns the length of normal data read, or -1 if an exception has
  * been thrown in this function.
  */
-static ssize_t socket_read_all(JNIEnv *env, jobject thisJ, int fd, 
+static ssize_t socket_read_all(JNIEnv *env, jobject thisJ, int fd,
         void *buffer, size_t len)
 {
     ssize_t ret;
@@ -554,7 +554,7 @@
     if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) {
         // To us, any of the above flags are a fatal error
 
-        jniThrowException(env, "java/io/IOException", 
+        jniThrowException(env, "java/io/IOException",
                 "Unexpected error or truncation during recvmsg()");
 
         return -1;
@@ -580,7 +580,7 @@
     unsigned char *buffer = (unsigned char *)buf;
     memset(&msg, 0, sizeof(msg));
 
-    jobjectArray outboundFds 
+    jobjectArray outboundFds
             = (jobjectArray)env->GetObjectField(
                 object, field_outboundFileDescriptors);
 
@@ -632,7 +632,7 @@
 
         msg.msg_iov = &iv;
         msg.msg_iovlen = 1;
-        
+
         do {
             ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
         } while (ret < 0 && errno == EINTR);
@@ -658,7 +658,7 @@
     int err;
 
     if (fileDescriptor == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return (jint)-1;
     }
 
@@ -685,7 +685,7 @@
     return (jint)buf;
 }
 
-static jint socket_readba (JNIEnv *env, jobject object, 
+static jint socket_readba (JNIEnv *env, jobject object,
         jbyteArray buffer, jint off, jint len, jobject fileDescriptor)
 {
     int fd;
@@ -693,7 +693,7 @@
     int ret;
 
     if (fileDescriptor == NULL || buffer == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return (jint)-1;
     }
 
@@ -720,7 +720,7 @@
         return (jint)-1;
     }
 
-    ret = socket_read_all(env, object, 
+    ret = socket_read_all(env, object,
             fd, byteBuffer + off, len);
 
     // A return of -1 above means an exception is pending
@@ -730,14 +730,14 @@
     return (jint) ((ret == 0) ? -1 : ret);
 }
 
-static void socket_write (JNIEnv *env, jobject object, 
+static void socket_write (JNIEnv *env, jobject object,
         jint b, jobject fileDescriptor)
 {
     int fd;
     int err;
 
     if (fileDescriptor == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
 
@@ -752,7 +752,7 @@
     // A return of -1 above means an exception is pending
 }
 
-static void socket_writeba (JNIEnv *env, jobject object, 
+static void socket_writeba (JNIEnv *env, jobject object,
         jbyteArray buffer, jint off, jint len, jobject fileDescriptor)
 {
     int fd;
@@ -760,7 +760,7 @@
     jbyte* byteBuffer;
 
     if (fileDescriptor == NULL || buffer == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
 
@@ -782,7 +782,7 @@
         return;
     }
 
-    err = socket_write_all(env, object, fd, 
+    err = socket_write_all(env, object, fd,
             byteBuffer + off, len);
 
     // A return of -1 above means an exception is pending
@@ -790,14 +790,14 @@
     env->ReleaseByteArrayElements(buffer, byteBuffer, JNI_ABORT);
 }
 
-static jobject socket_get_peer_credentials(JNIEnv *env, 
+static jobject socket_get_peer_credentials(JNIEnv *env,
         jobject object, jobject fileDescriptor)
 {
     int err;
     int fd;
 
     if (fileDescriptor == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return NULL;
     }
 
@@ -812,7 +812,7 @@
     memset(&creds, 0, sizeof(creds));
     socklen_t szCreds = sizeof(creds);
 
-    err = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds); 
+    err = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
 
     if (err < 0) {
         jniThrowIOException(env, errno);
@@ -823,20 +823,20 @@
         return NULL;
     }
 
-    return env->NewObject(class_Credentials, method_CredentialsInit, 
+    return env->NewObject(class_Credentials, method_CredentialsInit,
             creds.pid, creds.uid, creds.gid);
 }
 
 #if 0
 //TODO change this to return an instance of LocalSocketAddress
-static jobject socket_getSockName(JNIEnv *env, 
+static jobject socket_getSockName(JNIEnv *env,
         jobject object, jobject fileDescriptor)
 {
     int err;
     int fd;
 
     if (fileDescriptor == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return NULL;
     }
 
@@ -898,10 +898,10 @@
     {"readba_native", "([BIILjava/io/FileDescriptor;)I", (void*) socket_readba},
     {"writeba_native", "([BIILjava/io/FileDescriptor;)V", (void*) socket_writeba},
     {"write_native", "(ILjava/io/FileDescriptor;)V", (void*) socket_write},
-    {"getPeerCredentials_native", 
-            "(Ljava/io/FileDescriptor;)Landroid/net/Credentials;", 
+    {"getPeerCredentials_native",
+            "(Ljava/io/FileDescriptor;)Landroid/net/Credentials;",
             (void*) socket_get_peer_credentials}
-    //,{"getSockName_native", "(Ljava/io/FileDescriptor;)Ljava/lang/String;", 
+    //,{"getSockName_native", "(Ljava/io/FileDescriptor;)Ljava/lang/String;",
     //        (void *) socket_getSockName}
 
 };
@@ -916,14 +916,14 @@
         goto error;
     }
 
-    field_inboundFileDescriptors = env->GetFieldID(clazz, 
+    field_inboundFileDescriptors = env->GetFieldID(clazz,
             "inboundFileDescriptors", "[Ljava/io/FileDescriptor;");
 
     if (field_inboundFileDescriptors == NULL) {
         goto error;
     }
 
-    field_outboundFileDescriptors = env->GetFieldID(clazz, 
+    field_outboundFileDescriptors = env->GetFieldID(clazz,
             "outboundFileDescriptors", "[Ljava/io/FileDescriptor;");
 
     if (field_outboundFileDescriptors == NULL) {
@@ -931,7 +931,7 @@
     }
 
     class_Credentials = env->FindClass("android/net/Credentials");
-    
+
     if (class_Credentials == NULL) {
         goto error;
     }
@@ -946,7 +946,7 @@
 
     class_FileDescriptor = (jclass)env->NewGlobalRef(class_FileDescriptor);
 
-    method_CredentialsInit 
+    method_CredentialsInit
             = env->GetMethodID(class_Credentials, "<init>", "(III)V");
 
     if (method_CredentialsInit == NULL) {
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 3c4d2bf..66af965 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -2,16 +2,16 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -32,8 +32,7 @@
     jstring rvJ = NULL;
 
     if (keyJ == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException",
-                                "key must not be null.");
+        jniThrowNullPointerException(env, "key must not be null.");
         goto error;
     }
 
@@ -69,8 +68,7 @@
     jint result = defJ;
 
     if (keyJ == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException",
-                                "key must not be null.");
+        jniThrowNullPointerException(env, "key must not be null.");
         goto error;
     }
 
@@ -98,8 +96,7 @@
     jlong result = defJ;
 
     if (keyJ == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException",
-                                "key must not be null.");
+        jniThrowNullPointerException(env, "key must not be null.");
         goto error;
     }
 
@@ -127,8 +124,7 @@
     jboolean result = defJ;
 
     if (keyJ == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException",
-                                "key must not be null.");
+        jniThrowNullPointerException(env, "key must not be null.");
         goto error;
     }
 
@@ -163,8 +159,7 @@
     const char* val;
 
     if (keyJ == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException",
-                          "key must not be null.");
+        jniThrowNullPointerException(env, "key must not be null.");
         return ;
     }
     key = env->GetStringUTFChars(keyJ, NULL);
diff --git a/core/jni/android_pim_EventRecurrence.cpp b/core/jni/android_pim_EventRecurrence.cpp
index cbe99bc..9056c90 100644
--- a/core/jni/android_pim_EventRecurrence.cpp
+++ b/core/jni/android_pim_EventRecurrence.cpp
@@ -1,17 +1,17 @@
 /* //device/libs/android_runtime/android_pim_EventRecurrence.cpp

 **

-** Copyright 2006, The Android Open Source Project
+** Copyright 2006, 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 

+** 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 

+**     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 

+** 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.

 */

 

@@ -84,8 +84,7 @@
 EventRecurrence_parse(JNIEnv* env, jobject This, jstring jstr)

 {

     if (jstr == NULL) {

-        jniThrowException(env, "java/lang/NullPointerException", 

-                "EventRecurrence.parse str parameter null"); 

+        jniThrowNullPointerException(env, "EventRecurrence.parse str parameter null");

         return ;

     }

     jboolean isCopy;

@@ -112,8 +111,8 @@
     if (er.until.size() > 0) {

         untilStr = env->NewString(er.until.string(), er.until.size());

         if (untilStr == NULL) {

-            jniThrowException(env, "java/lang/RuntimeException", 

-                    "EventRecurrence.parse error setting field 'until'"); 

+            jniThrowException(env, "java/lang/RuntimeException",

+                    "EventRecurrence.parse error setting field 'until'");

             return ;

         }

     } else {

@@ -132,7 +131,7 @@
     SET_ARRAY_AND_CHECK(byday)

     // we'll just set the bydayCount field twice, it'll be less code total

     if (set_array(env, er.bydayCount, er.bydayNum, This, bydayNum_fields)

-            != NO_ERROR) { 

+            != NO_ERROR) {

         jniThrowException(env, "java/lang/RuntimeException",

                 "EventRecurrence.parse error setting field bydayNum or "

                 "bydayCount.");

@@ -196,4 +195,3 @@
 }

 

 }; // namespace android

-

diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 6b90541..0d0f5fa 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -2,22 +2,23 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
 #define LOG_TAG "AndroidUnicode"
 
 #include "JNIHelp.h"
+#include "ScopedPrimitiveArray.h"
 #include <android_runtime/AndroidRuntime.h>
 #include "utils/misc.h"
 #include "utils/Log.h"
@@ -49,19 +50,21 @@
 };
 
 namespace android {
-    
+
 static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, jbyteArray destArray, int count)
 {
-    jchar* src = env->GetCharArrayElements(srcArray, NULL);
-    jbyte* dest = env->GetByteArrayElements(destArray, NULL);
-    if (src == NULL || dest == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
-        goto DIRECTION_END;
+    ScopedCharArrayRO src(env, srcArray);
+    if (src.get() == NULL) {
+        return;
+    }
+    ScopedByteArrayRW dest(env, destArray);
+    if (dest.get() == NULL) {
+        return;
     }
 
     if (env->GetArrayLength(srcArray) < count || env->GetArrayLength(destArray) < count) {
         jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
-        goto DIRECTION_END;
+        return;
     }
 
     for (int i = 0; i < count; i++) {
@@ -87,10 +90,6 @@
                 dest[i] = directionality_map[dir];
         }
     }
-    
-DIRECTION_END:
-    env->ReleaseCharArrayElements(srcArray, src, JNI_ABORT);
-    env->ReleaseByteArrayElements(destArray, dest, JNI_ABORT);
 }
 
 static jint getEastAsianWidth(JNIEnv* env, jobject obj, jchar input)
@@ -105,18 +104,20 @@
 static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
                                int start, int count, jbyteArray destArray)
 {
-    jchar* src = env->GetCharArrayElements(srcArray, NULL);
-    jbyte* dest = env->GetByteArrayElements(destArray, NULL);
-    if (src == NULL || dest == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
-        goto EA_END;
+    ScopedCharArrayRO src(env, srcArray);
+    if (src.get() == NULL) {
+        return;
+    }
+    ScopedByteArrayRW dest(env, destArray);
+    if (dest.get() == NULL) {
+        return;
     }
 
     if (start < 0 || start > start + count
             || env->GetArrayLength(srcArray) < (start + count)
             || env->GetArrayLength(destArray) < count) {
         jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
-        goto EA_END;
+        return;
     }
 
     for (int i = 0; i < count; i++) {
@@ -141,26 +142,19 @@
             dest[i] = width;
         }
     }
-
-EA_END:
-    env->ReleaseCharArrayElements(srcArray, src, JNI_ABORT);
-    env->ReleaseByteArrayElements(destArray, dest, JNI_ABORT);
 }
 
 static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, int start, int count)
 {
-    jchar* data = env->GetCharArrayElements(charArray, NULL);
-    bool ret = false;
-
-    if (data == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
-        goto MIRROR_END;
+    ScopedCharArrayRW data(env, charArray);
+    if (data.get() == NULL) {
+        return false;
     }
 
     if (start < 0 || start > start + count
             || env->GetArrayLength(charArray) < start + count) {
         jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
-        goto MIRROR_END;
+        return false;
     }
 
     for (int i = start; i < start + count; i++) {
@@ -171,17 +165,14 @@
 
         if (c1 != c2) {
             data[i] = c2;
-            ret = true;
+            return true;
         }
     }
-
-MIRROR_END:
-    env->ReleaseCharArrayElements(charArray, data, JNI_ABORT);
-	return ret;
+    return false;
 }
 
 static jchar getMirror(JNIEnv* env, jobject obj, jchar c)
-{   
+{
     return u_charMirror(c);
 }
 
@@ -202,7 +193,7 @@
 {
     jclass clazz = env->FindClass("android/text/AndroidCharacter");
     LOG_ASSERT(clazz, "Cannot find android/text/AndroidCharacter");
-    
+
     return AndroidRuntime::registerNativeMethods(env, "android/text/AndroidCharacter",
             gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 65b5990..8ea7e90 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -2,16 +2,16 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -24,6 +24,8 @@
 
 #include "jni.h"
 #include "JNIHelp.h"
+#include "ScopedStringChars.h"
+#include "ScopedUtfChars.h"
 #include "android_util_Binder.h"
 #include <utils/misc.h>
 #include <android_runtime/AndroidRuntime.h>
@@ -121,8 +123,8 @@
 
     LOGV("openAsset in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "fileName");
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
         return -1;
     }
 
@@ -132,15 +134,12 @@
         return -1;
     }
 
-    const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
-    Asset* a = am->open(fileName8, (Asset::AccessMode)mode);
+    Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
 
     if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
-        env->ReleaseStringUTFChars(fileName, fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
         return -1;
     }
-    env->ReleaseStringUTFChars(fileName, fileName8);
 
     //printf("Created Asset Stream: %p\n", a);
 
@@ -152,30 +151,30 @@
     off64_t startOffset, length;
     int fd = a->openFileDescriptor(&startOffset, &length);
     delete a;
-    
+
     if (fd < 0) {
         jniThrowException(env, "java/io/FileNotFoundException",
                 "This file can not be opened as a file descriptor; it is probably compressed");
         return NULL;
     }
-    
+
     jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
     if (offsets == NULL) {
         close(fd);
         return NULL;
     }
-    
+
     offsets[0] = startOffset;
     offsets[1] = length;
-    
+
     env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
-    
+
     jobject fileDesc = newFileDescriptor(env, fd);
     if (fileDesc == NULL) {
         close(fd);
         return NULL;
     }
-    
+
     return newParcelFileDescriptor(env, fileDesc);
 }
 
@@ -189,20 +188,17 @@
 
     LOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "fileName");
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
         return NULL;
     }
 
-    const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
-    Asset* a = am->open(fileName8, Asset::ACCESS_RANDOM);
+    Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
 
     if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
-        env->ReleaseStringUTFChars(fileName, fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
         return NULL;
     }
-    env->ReleaseStringUTFChars(fileName, fileName8);
 
     //printf("Created Asset Stream: %p\n", a);
 
@@ -221,8 +217,8 @@
 
     LOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "fileName");
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
         return -1;
     }
 
@@ -232,17 +228,14 @@
         return -1;
     }
 
-    const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
     Asset* a = cookie
-        ? am->openNonAsset((void*)cookie, fileName8, (Asset::AccessMode)mode)
-        : am->openNonAsset(fileName8, (Asset::AccessMode)mode);
+        ? am->openNonAsset((void*)cookie, fileName8.c_str(), (Asset::AccessMode)mode)
+        : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
 
     if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
-        env->ReleaseStringUTFChars(fileName, fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
         return -1;
     }
-    env->ReleaseStringUTFChars(fileName, fileName8);
 
     //printf("Created Asset Stream: %p\n", a);
 
@@ -261,22 +254,19 @@
 
     LOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL ) {
-        jniThrowException(env, "java/lang/NullPointerException", "fileName");
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
         return NULL;
     }
 
-    const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
     Asset* a = cookie
-        ? am->openNonAsset((void*)cookie, fileName8, Asset::ACCESS_RANDOM)
-        : am->openNonAsset(fileName8, Asset::ACCESS_RANDOM);
+        ? am->openNonAsset((void*)cookie, fileName8.c_str(), Asset::ACCESS_RANDOM)
+        : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
 
     if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
-        env->ReleaseStringUTFChars(fileName, fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
         return NULL;
     }
-    env->ReleaseStringUTFChars(fileName, fileName8);
 
     //printf("Created Asset Stream: %p\n", a);
 
@@ -291,19 +281,15 @@
         return NULL;
     }
 
-    if (fileName == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "fileName");
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
         return NULL;
     }
 
-    const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
-
-    AssetDir* dir = am->openDir(fileName8);
-
-    env->ReleaseStringUTFChars(fileName, fileName8);
+    AssetDir* dir = am->openDir(fileName8.c_str());
 
     if (dir == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
         return NULL;
     }
 
@@ -347,7 +333,7 @@
     //printf("Destroying Asset Stream: %p\n", a);
 
     if (a == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "asset");
+        jniThrowNullPointerException(env, "asset");
         return;
     }
 
@@ -360,7 +346,7 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "asset");
+        jniThrowNullPointerException(env, "asset");
         return -1;
     }
 
@@ -376,14 +362,14 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL || bArray == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "asset");
+        jniThrowNullPointerException(env, "asset");
         return -1;
     }
 
     if (len == 0) {
         return 0;
     }
-    
+
     jsize bLen = env->GetArrayLength(bArray);
     if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
         jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
@@ -409,7 +395,7 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "asset");
+        jniThrowNullPointerException(env, "asset");
         return -1;
     }
 
@@ -423,7 +409,7 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "asset");
+        jniThrowNullPointerException(env, "asset");
         return -1;
     }
 
@@ -436,7 +422,7 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "asset");
+        jniThrowNullPointerException(env, "asset");
         return -1;
     }
 
@@ -446,9 +432,9 @@
 static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
                                                        jstring path)
 {
-    if (path == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "path");
-        return JNI_FALSE;
+    ScopedUtfChars path8(env, path);
+    if (path8.c_str() == NULL) {
+        return NULL;
     }
 
     AssetManager* am = assetManagerForJavaObject(env, clazz);
@@ -456,12 +442,8 @@
         return JNI_FALSE;
     }
 
-    const char* path8 = env->GetStringUTFChars(path, NULL);
-
     void* cookie;
-    bool res = am->addAssetPath(String8(path8), &cookie);
-
-    env->ReleaseStringUTFChars(path, path8);
+    bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
 
     return (res) ? (jint)cookie : 0;
 }
@@ -478,21 +460,17 @@
 static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
                                                 jstring locale)
 {
-    if (locale == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "locale");
+    ScopedUtfChars locale8(env, locale);
+    if (locale8.c_str() == NULL) {
         return;
     }
 
-    const char* locale8 = env->GetStringUTFChars(locale, NULL);
-
     AssetManager* am = assetManagerForJavaObject(env, clazz);
     if (am == NULL) {
         return;
     }
 
-    am->setLocale(locale8);
-
-    env->ReleaseStringUTFChars(locale, locale8);
+    am->setLocale(locale8.c_str());
 }
 
 static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
@@ -543,9 +521,9 @@
 
     ResTable_config config;
     memset(&config, 0, sizeof(config));
-    
+
     const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
-    
+
     config.mcc = (uint16_t)mcc;
     config.mnc = (uint16_t)mnc;
     config.orientation = (uint8_t)orientation;
@@ -563,7 +541,7 @@
     config.sdkVersion = (uint16_t)sdkVersion;
     config.minorVersion = 0;
     am->setConfiguration(config, locale8);
-    
+
     if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
 }
 
@@ -572,8 +550,8 @@
                                                             jstring defType,
                                                             jstring defPackage)
 {
-    if (name == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "name");
+    ScopedStringChars name16(env, name);
+    if (name16.get() == NULL) {
         return 0;
     }
 
@@ -582,8 +560,6 @@
         return 0;
     }
 
-    const char16_t* name16 = env->GetStringChars(name, NULL);
-    jsize nameLen = env->GetStringLength(name);
     const char16_t* defType16 = defType
         ? env->GetStringChars(defType, NULL) : NULL;
     jsize defTypeLen = defType
@@ -594,7 +570,7 @@
         ? env->GetStringLength(defPackage) : 0;
 
     jint ident = am->getResources().identifierForName(
-        name16, nameLen, defType16, defTypeLen, defPackage16, defPackageLen);
+        name16.get(), name16.size(), defType16, defTypeLen, defPackage16, defPackageLen);
 
     if (defPackage16) {
         env->ReleaseStringChars(defPackage, defPackage16);
@@ -602,7 +578,6 @@
     if (defType16) {
         env->ReleaseStringChars(defType, defType16);
     }
-    env->ReleaseStringChars(name, name16);
 
     return ident;
 }
@@ -614,12 +589,12 @@
     if (am == NULL) {
         return NULL;
     }
-    
+
     ResTable::resource_name name;
     if (!am->getResources().getResourceName(resid, &name)) {
         return NULL;
     }
-    
+
     String16 str;
     if (name.package != NULL) {
         str.setTo(name.package, name.packageLen);
@@ -638,7 +613,7 @@
         }
         str.append(name.name, name.nameLen);
     }
-    
+
     return env->NewString((const jchar*)str.string(), str.size());
 }
 
@@ -649,16 +624,16 @@
     if (am == NULL) {
         return NULL;
     }
-    
+
     ResTable::resource_name name;
     if (!am->getResources().getResourceName(resid, &name)) {
         return NULL;
     }
-    
+
     if (name.package != NULL) {
         return env->NewString((const jchar*)name.package, name.packageLen);
     }
-    
+
     return NULL;
 }
 
@@ -669,16 +644,16 @@
     if (am == NULL) {
         return NULL;
     }
-    
+
     ResTable::resource_name name;
     if (!am->getResources().getResourceName(resid, &name)) {
         return NULL;
     }
-    
+
     if (name.type != NULL) {
         return env->NewString((const jchar*)name.type, name.typeLen);
     }
-    
+
     return NULL;
 }
 
@@ -689,16 +664,16 @@
     if (am == NULL) {
         return NULL;
     }
-    
+
     ResTable::resource_name name;
     if (!am->getResources().getResourceName(resid, &name)) {
         return NULL;
     }
-    
+
     if (name.name != NULL) {
         return env->NewString((const jchar*)name.name, name.nameLen);
     }
-    
+
     return NULL;
 }
 
@@ -746,10 +721,10 @@
         return 0;
     }
     const ResTable& res(am->getResources());
-    
+
     // Now lock down the resource object and start pulling stuff from it.
     res.lock();
-    
+
     ssize_t block = -1;
     Res_value value;
 
@@ -770,7 +745,7 @@
     if (block < 0) {
         return block;
     }
-    
+
     uint32_t ref = ident;
     if (resolve) {
         block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
@@ -881,25 +856,9 @@
 {
     ResTable::Theme* theme = (ResTable::Theme*)themeInt;
     const ResTable& res(theme->getResTable());
-    
-    if (tag == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "tag");
-        return;
-    }
-    
-    const char* tag8 = env->GetStringUTFChars(tag, NULL);
-    const char* prefix8 = NULL;
-    if (prefix != NULL) {
-        prefix8 = env->GetStringUTFChars(prefix, NULL);
-    }
-    
+
     // XXX Need to use params.
     theme->dumpToLog();
-    
-    if (prefix8 != NULL) {
-        env->ReleaseStringUTFChars(prefix, prefix8);
-    }
-    env->ReleaseStringUTFChars(tag, tag8);
 }
 
 static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
@@ -912,21 +871,21 @@
                                                         jintArray outIndices)
 {
     if (themeToken == 0) {
-        jniThrowException(env, "java/lang/NullPointerException", "theme token");
+        jniThrowNullPointerException(env, "theme token");
         return JNI_FALSE;
     }
     if (attrs == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "attrs");
+        jniThrowNullPointerException(env, "attrs");
         return JNI_FALSE;
     }
     if (outValues == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "out values");
+        jniThrowNullPointerException(env, "out values");
         return JNI_FALSE;
     }
 
     DEBUG_STYLES(LOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
         themeToken, defStyleAttr, defStyleRes, xmlParserToken));
-        
+
     ResTable::Theme* theme = (ResTable::Theme*)themeToken;
     const ResTable& res = theme->getResTable();
     ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
@@ -942,7 +901,6 @@
 
     jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
     if (src == NULL) {
-        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
 
@@ -950,7 +908,6 @@
     jint* dest = baseDest;
     if (dest == NULL) {
         env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
 
@@ -1025,7 +982,7 @@
         const uint32_t curIdent = (uint32_t)src[ii];
 
         DEBUG_STYLES(LOGI("RETRIEVING ATTR 0x%08x...", curIdent));
-        
+
         // Try to find a value for this attribute...  we prioritize values
         // coming from, first XML attributes, then XML style, then default
         // style, and finally the theme.
@@ -1128,12 +1085,12 @@
         dest[STYLE_RESOURCE_ID] = resid;
         dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
         dest[STYLE_DENSITY] = config.density;
-        
+
         if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
             indicesIdx++;
             indices[indicesIdx] = ii;
         }
-        
+
         dest += STYLE_NUM_ENTRIES;
     }
 
@@ -1156,18 +1113,18 @@
                                                         jintArray outIndices)
 {
     if (xmlParserToken == 0) {
-        jniThrowException(env, "java/lang/NullPointerException", "xmlParserToken");
+        jniThrowNullPointerException(env, "xmlParserToken");
         return JNI_FALSE;
     }
     if (attrs == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "attrs");
+        jniThrowNullPointerException(env, "attrs");
         return JNI_FALSE;
     }
     if (outValues == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "out values");
+        jniThrowNullPointerException(env, "out values");
         return JNI_FALSE;
     }
-    
+
     AssetManager* am = assetManagerForJavaObject(env, clazz);
     if (am == NULL) {
         return JNI_FALSE;
@@ -1176,28 +1133,26 @@
     ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
     ResTable_config config;
     Res_value value;
-    
+
     const jsize NI = env->GetArrayLength(attrs);
     const jsize NV = env->GetArrayLength(outValues);
     if (NV < (NI*STYLE_NUM_ENTRIES)) {
         jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
         return JNI_FALSE;
     }
-    
+
     jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
     if (src == NULL) {
-        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
-    
+
     jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
     jint* dest = baseDest;
     if (dest == NULL) {
         env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
-    
+
     jint* indices = NULL;
     int indicesIdx = 0;
     if (outIndices != NULL) {
@@ -1208,27 +1163,27 @@
 
     // Now lock down the resource object and start pulling stuff from it.
     res.lock();
-    
+
     // Retrieve the XML attributes, if requested.
     const jsize NX = xmlParser->getAttributeCount();
     jsize ix=0;
     uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
-    
+
     static const ssize_t kXmlBlock = 0x10000000;
-    
+
     // Now iterate through all of the attributes that the client has requested,
     // filling in each with whatever data we can find.
     ssize_t block = 0;
     uint32_t typeSetFlags;
     for (jsize ii=0; ii<NI; ii++) {
         const uint32_t curIdent = (uint32_t)src[ii];
-        
+
         // Try to find a value for this attribute...
         value.dataType = Res_value::TYPE_NULL;
         value.data = 0;
         typeSetFlags = 0;
         config.density = 0;
-        
+
         // Skip through XML attributes until the end or the next possible match.
         while (ix < NX && curIdent > curXmlAttr) {
             ix++;
@@ -1241,7 +1196,7 @@
             ix++;
             curXmlAttr = xmlParser->getAttributeNameResID(ix);
         }
-        
+
         //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
         uint32_t resid = 0;
         if (value.dataType != Res_value::TYPE_NULL) {
@@ -1257,14 +1212,14 @@
 #endif
             if (newBlock >= 0) block = newBlock;
         }
-        
+
         // Deal with the special @null value -- it turns back to TYPE_NULL.
         if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
             value.dataType = Res_value::TYPE_NULL;
         }
-        
+
         //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
-        
+
         // Write the final value back to Java.
         dest[STYLE_TYPE] = value.dataType;
         dest[STYLE_DATA] = value.data;
@@ -1273,25 +1228,25 @@
         dest[STYLE_RESOURCE_ID] = resid;
         dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
         dest[STYLE_DENSITY] = config.density;
-        
+
         if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
             indicesIdx++;
             indices[indicesIdx] = ii;
         }
-        
+
         dest += STYLE_NUM_ENTRIES;
     }
-    
+
     res.unlock();
-    
+
     if (indices != NULL) {
         indices[0] = indicesIdx;
         env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
     }
-    
+
     env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
     env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-    
+
     return JNI_TRUE;
 }
 
@@ -1303,12 +1258,12 @@
         return 0;
     }
     const ResTable& res(am->getResources());
-    
+
     res.lock();
     const ResTable::bag_entry* defStyleEnt = NULL;
     ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
     res.unlock();
-    
+
     return bagOff;
 }
 
@@ -1317,10 +1272,10 @@
                                                         jintArray outValues)
 {
     if (outValues == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "out values");
+        jniThrowNullPointerException(env, "out values");
         return JNI_FALSE;
     }
-    
+
     AssetManager* am = assetManagerForJavaObject(env, clazz);
     if (am == NULL) {
         return JNI_FALSE;
@@ -1329,25 +1284,25 @@
     ResTable_config config;
     Res_value value;
     ssize_t block;
-    
+
     const jsize NV = env->GetArrayLength(outValues);
-    
+
     jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
     jint* dest = baseDest;
     if (dest == NULL) {
         jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
-    
+
     // Now lock down the resource object and start pulling stuff from it.
     res.lock();
-    
+
     const ResTable::bag_entry* arrayEnt = NULL;
     uint32_t arrayTypeSetFlags = 0;
     ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
     const ResTable::bag_entry* endArrayEnt = arrayEnt +
         (bagOff >= 0 ? bagOff : 0);
-    
+
     int i = 0;
     uint32_t typeSetFlags;
     while (i < NV && arrayEnt < endArrayEnt) {
@@ -1355,7 +1310,7 @@
         typeSetFlags = arrayTypeSetFlags;
         config.density = 0;
         value = arrayEnt->map.value;
-                
+
         uint32_t resid = 0;
         if (value.dataType != Res_value::TYPE_NULL) {
             // Take care of resolving the found resource to its final value.
@@ -1389,13 +1344,13 @@
         i+= STYLE_NUM_ENTRIES;
         arrayEnt++;
     }
-    
+
     i /= STYLE_NUM_ENTRIES;
-    
+
     res.unlock();
-    
+
     env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
-    
+
     return i;
 }
 
@@ -1410,22 +1365,19 @@
 
     LOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", "fileName");
+    ScopedUtfChars fileName8(env, fileName);
+    if (fileName8.c_str() == NULL) {
         return 0;
     }
 
-    const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
     Asset* a = cookie
-        ? am->openNonAsset((void*)cookie, fileName8, Asset::ACCESS_BUFFER)
-        : am->openNonAsset(fileName8, Asset::ACCESS_BUFFER);
+        ? am->openNonAsset((void*)cookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
+        : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER);
 
     if (a == NULL) {
-        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
-        env->ReleaseStringUTFChars(fileName, fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
         return 0;
     }
-    env->ReleaseStringUTFChars(fileName, fileName8);
 
     ResXMLTree* block = new ResXMLTree();
     status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
@@ -1457,7 +1409,6 @@
 
     jintArray array = env->NewIntArray(N * 2);
     if (array == NULL) {
-        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         res.unlockBag(startOfBag);
         return NULL;
     }
@@ -1468,20 +1419,20 @@
         jint stringIndex = -1;
         jint stringBlock = 0;
         value = bag->map.value;
-        
+
         // Take care of resolving the found resource to its final value.
         stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
         if (value.dataType == Res_value::TYPE_STRING) {
             stringIndex = value.data;
         }
-        
+
 #if THROW_ON_BAD_ID
         if (stringBlock == BAD_INDEX) {
             jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
             return array;
         }
 #endif
-    
+
         //todo: It might be faster to allocate a C array to contain
         //      the blocknums and indices, put them in there and then
         //      do just one SetIntArrayRegion()
@@ -1581,7 +1532,6 @@
 
     jintArray array = env->NewIntArray(N);
     if (array == NULL) {
-        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         res.unlockBag(startOfBag);
         return NULL;
     }
@@ -1590,7 +1540,7 @@
     const ResTable::bag_entry* bag = startOfBag;
     for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
         value = bag->map.value;
-        
+
         // Take care of resolving the found resource to its final value.
         ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
 #if THROW_ON_BAD_ID
@@ -1645,7 +1595,7 @@
     if (alloc.length() <= 0) {
         return NULL;
     }
-    
+
     jstring str = env->NewStringUTF(alloc.string());
     return str;
 }
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index eb1c437..8618b79 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -993,7 +993,7 @@
                                                 jobject replyObj, jint flags)
 {
     if (dataObj == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return JNI_FALSE;
     }
 
@@ -1045,7 +1045,7 @@
                                                jobject recipient, jint flags)
 {
     if (recipient == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
 
@@ -1077,7 +1077,7 @@
 {
     jboolean res = JNI_FALSE;
     if (recipient == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return res;
     }
 
@@ -1166,7 +1166,7 @@
     clazz = env->FindClass("java/lang/Error");
     LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error");
     gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    
+
     clazz = env->FindClass(kBinderProxyPathName);
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy");
 
@@ -1474,7 +1474,7 @@
                                                     jstring name, jint mode)
 {
     if (name == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return NULL;
     }
     const jchar* str = env->GetStringCritical(name, 0);
@@ -1522,7 +1522,7 @@
 static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jobject clazz, jobject orig)
 {
     if (orig == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return NULL;
     }
     int origfd = env->GetIntField(orig, gFileDescriptorOffsets.mDescriptor);
@@ -1533,7 +1533,7 @@
 
     int fd = dup(origfd);
     if (fd < 0) {
-        jniThrowException(env, "java/io/IOException", strerror(errno));
+        jniThrowIOException(env, errno);
         return NULL;
     }
     jobject object = newFileDescriptor(env, fd);
@@ -1546,7 +1546,7 @@
 static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
 {
     if (object == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
     int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
@@ -1560,7 +1560,7 @@
 static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
 {
     if (object == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
     int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index e43478c..91d37d3 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -151,7 +151,7 @@
                                              jintArray tags,
                                              jobject out) {
     if (tags == NULL || out == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
 
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 7dfb716..0068de7 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -2,16 +2,16 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -107,10 +107,10 @@
 static void fakeProcessEntry(void* arg)
 {
     String8* cls = (String8*)arg;
-    
+
     AndroidRuntime* jr = AndroidRuntime::getRuntime();
     jr->callMain(cls->string(), 0, NULL);
-        
+
     delete cls;
 }
 
@@ -132,10 +132,10 @@
 jint android_os_Process_getUidForName(JNIEnv* env, jobject clazz, jstring name)
 {
     if (name == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return -1;
     }
-    
+
     const jchar* str16 = env->GetStringCritical(name, 0);
     String8 name8;
     if (str16) {
@@ -163,10 +163,10 @@
 jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name)
 {
     if (name == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return -1;
     }
-    
+
     const jchar* str16 = env->GetStringCritical(name, 0);
     String8 name8;
     if (str16) {
@@ -200,14 +200,14 @@
     }
 }
 
-void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp) 
+void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
 {
     DIR *d;
     FILE *fp;
     char proc_path[255];
     struct dirent *de;
 
-    if (grp > ANDROID_TGROUP_MAX || grp < 0) { 
+    if (grp > ANDROID_TGROUP_MAX || grp < 0) {
         signalExceptionForGroupError(env, clazz, EINVAL);
         return;
     }
@@ -225,7 +225,7 @@
         cmdline[rc] = 0;
         close(fd);
     }
-    
+
     if (grp == ANDROID_TGROUP_BG_NONINTERACT) {
         LOGD("setProcessGroup: vvv pid %d (%s)", pid, cmdline);
     } else {
@@ -260,7 +260,7 @@
             // This task wants to stay at background
             continue;
         }
-     
+
         if (androidSetThreadSchedulingGroup(t_pid, grp) != NO_ERROR) {
             signalExceptionForGroupError(env, clazz, errno);
             break;
@@ -312,7 +312,7 @@
             signalExceptionForGroupError(env, clazz, errno);
         }
     }
-    
+
     //LOGI("Setting priority of %d: %d, getpriority returns %d\n",
     //     pid, pri, getpriority(PRIO_PROCESS, pid));
 }
@@ -358,10 +358,10 @@
 void android_os_Process_setArgV0(JNIEnv* env, jobject clazz, jstring name)
 {
     if (name == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
-    
+
     const jchar* str = env->GetStringCritical(name, 0);
     String8 name8;
     if (str) {
@@ -406,16 +406,16 @@
 static jlong android_os_Process_getFreeMemory(JNIEnv* env, jobject clazz)
 {
     int fd = open("/proc/meminfo", O_RDONLY);
-    
+
     if (fd < 0) {
         LOGW("Unable to open /proc/meminfo");
         return -1;
     }
-    
+
     char buffer[256];
     const int len = read(fd, buffer, sizeof(buffer)-1);
     close(fd);
-    
+
     if (len < 0) {
         LOGW("Unable to read /proc/meminfo");
         return -1;
@@ -424,10 +424,10 @@
 
     int numFound = 0;
     jlong mem = 0;
-    
+
     static const char* const sums[] = { "MemFree:", "Cached:", NULL };
     static const int sumsLen[] = { strlen("MemFree:"), strlen("Cached:"), NULL };
-    
+
     char* p = buffer;
     while (*p && numFound < 2) {
         int i = 0;
@@ -450,7 +450,7 @@
         }
         p++;
     }
-    
+
     return numFound > 0 ? mem : -1;
 }
 
@@ -458,71 +458,71 @@
                                       jobjectArray reqFields, jlongArray outFields)
 {
     //LOGI("getMemInfo: %p %p", reqFields, outFields);
-    
+
     if (fileStr == NULL || reqFields == NULL || outFields == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
-    
+
     const char* file8 = env->GetStringUTFChars(fileStr, NULL);
     if (file8 == NULL) {
         return;
     }
     String8 file(file8);
     env->ReleaseStringUTFChars(fileStr, file8);
-    
+
     jsize count = env->GetArrayLength(reqFields);
     if (count > env->GetArrayLength(outFields)) {
         jniThrowException(env, "java/lang/IllegalArgumentException", "Array lengths differ");
         return;
     }
-    
+
     Vector<String8> fields;
     int i;
-    
+
     for (i=0; i<count; i++) {
         jobject obj = env->GetObjectArrayElement(reqFields, i);
         if (obj != NULL) {
             const char* str8 = env->GetStringUTFChars((jstring)obj, NULL);
             //LOGI("String at %d: %p = %s", i, obj, str8);
             if (str8 == NULL) {
-                jniThrowException(env, "java/lang/NullPointerException", "Element in reqFields");
+                jniThrowNullPointerException(env, "Element in reqFields");
                 return;
             }
             fields.add(String8(str8));
             env->ReleaseStringUTFChars((jstring)obj, str8);
         } else {
-            jniThrowException(env, "java/lang/NullPointerException", "Element in reqFields");
+            jniThrowNullPointerException(env, "Element in reqFields");
             return;
         }
     }
-    
+
     jlong* sizesArray = env->GetLongArrayElements(outFields, 0);
     if (sizesArray == NULL) {
         return;
     }
-    
+
     //LOGI("Clearing %d sizes", count);
     for (i=0; i<count; i++) {
         sizesArray[i] = 0;
     }
-    
+
     int fd = open(file.string(), O_RDONLY);
-    
+
     if (fd >= 0) {
         const size_t BUFFER_SIZE = 2048;
         char* buffer = (char*)malloc(BUFFER_SIZE);
         int len = read(fd, buffer, BUFFER_SIZE-1);
         close(fd);
-        
+
         if (len < 0) {
             LOGW("Unable to read %s", file.string());
             len = 0;
         }
         buffer[len] = 0;
-    
+
         int foundCount = 0;
-        
+
         char* p = buffer;
         while (*p && foundCount < count) {
             bool skipToEol = true;
@@ -555,12 +555,12 @@
                 }
             }
         }
-        
+
         free(buffer);
     } else {
         LOGW("Unable to open %s", file.string());
     }
-    
+
     //LOGI("Done!");
     env->ReleaseLongArrayElements(outFields, sizesArray, 0);
 }
@@ -569,33 +569,33 @@
                                      jstring file, jintArray lastArray)
 {
     if (file == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return NULL;
     }
-    
+
     const char* file8 = env->GetStringUTFChars(file, NULL);
     if (file8 == NULL) {
         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
         return NULL;
     }
-    
+
     DIR* dirp = opendir(file8);
-    
+
     env->ReleaseStringUTFChars(file, file8);
-    
+
     if(dirp == NULL) {
         return NULL;
     }
-    
+
     jsize curCount = 0;
     jint* curData = NULL;
     if (lastArray != NULL) {
         curCount = env->GetArrayLength(lastArray);
         curData = env->GetIntArrayElements(lastArray, 0);
     }
-    
+
     jint curPos = 0;
-    
+
     struct dirent* entry;
     while ((entry=readdir(dirp)) != NULL) {
         const char* p = entry->d_name;
@@ -604,7 +604,7 @@
             p++;
         }
         if (*p != 0) continue;
-        
+
         char* end;
         int pid = strtol(entry->d_name, &end, 10);
         //LOGI("File %s pid=%d\n", entry->d_name, pid);
@@ -625,26 +625,26 @@
             curCount = newCount;
             curData = newData;
         }
-        
+
         curData[curPos] = pid;
         curPos++;
     }
-    
+
     closedir(dirp);
-    
+
     if (curData != NULL && curPos > 0) {
         qsort(curData, curPos, sizeof(jint), pid_compare);
     }
-    
+
     while (curPos < curCount) {
         curData[curPos] = -1;
         curPos++;
     }
-    
+
     if (curData != NULL) {
         env->ReleaseIntArrayElements(lastArray, curData, 0);
     }
-    
+
     return lastArray;
 }
 
@@ -660,15 +660,15 @@
 };
 
 jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz,
-        char* buffer, jint startIndex, jint endIndex, jintArray format, 
+        char* buffer, jint startIndex, jint endIndex, jintArray format,
         jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
 {
-    
+
     const jsize NF = env->GetArrayLength(format);
     const jsize NS = outStrings ? env->GetArrayLength(outStrings) : 0;
     const jsize NL = outLongs ? env->GetArrayLength(outLongs) : 0;
     const jsize NR = outFloats ? env->GetArrayLength(outFloats) : 0;
-    
+
     jint* formatData = env->GetIntArrayElements(format, 0);
     jlong* longsData = outLongs ?
         env->GetLongArrayElements(outLongs, 0) : NULL;
@@ -691,9 +691,9 @@
 
     jsize i = startIndex;
     jsize di = 0;
-    
+
     jboolean res = JNI_TRUE;
-    
+
     for (jsize fi=0; fi<NF; fi++) {
         const jint mode = formatData[fi];
         if ((mode&PROC_PARENS) != 0) {
@@ -705,7 +705,7 @@
             res = JNI_FALSE;
             break;
         }
-        
+
         jsize end = -1;
         if ((mode&PROC_PARENS) != 0) {
             while (buffer[i] != ')' && i < endIndex) {
@@ -720,7 +720,7 @@
         if (end < 0) {
             end = i;
         }
-        
+
         if (i < endIndex) {
             i++;
             if ((mode&PROC_COMBINE) != 0) {
@@ -729,9 +729,9 @@
                 }
             }
         }
-        
+
         //LOGI("Field %d: %d-%d dest=%d mode=0x%x\n", i, start, end, di, mode);
-        
+
         if ((mode&(PROC_OUT_FLOAT|PROC_OUT_LONG|PROC_OUT_STRING)) != 0) {
             char c = buffer[end];
             buffer[end] = 0;
@@ -751,7 +751,7 @@
             di++;
         }
     }
-    
+
     env->ReleaseIntArrayElements(format, formatData, 0);
     if (longsData != NULL) {
         env->ReleaseLongArrayElements(outLongs, longsData, 0);
@@ -759,22 +759,22 @@
     if (floatsData != NULL) {
         env->ReleaseFloatArrayElements(outFloats, floatsData, 0);
     }
-    
+
     return res;
 }
 
 jboolean android_os_Process_parseProcLine(JNIEnv* env, jobject clazz,
-        jbyteArray buffer, jint startIndex, jint endIndex, jintArray format, 
+        jbyteArray buffer, jint startIndex, jint endIndex, jintArray format,
         jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
 {
         jbyte* bufferArray = env->GetByteArrayElements(buffer, NULL);
 
-        jboolean result = android_os_Process_parseProcLineArray(env, clazz, 
-                (char*) bufferArray, startIndex, endIndex, format, outStrings, 
+        jboolean result = android_os_Process_parseProcLineArray(env, clazz,
+                (char*) bufferArray, startIndex, endIndex, format, outStrings,
                 outLongs, outFloats);
-                
+
         env->ReleaseByteArrayElements(buffer, bufferArray, 0);
-        
+
         return result;
 }
 
@@ -783,7 +783,7 @@
         jlongArray outLongs, jfloatArray outFloats)
 {
     if (file == NULL || format == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return JNI_FALSE;
     }
 
@@ -794,32 +794,32 @@
     }
     int fd = open(file8, O_RDONLY);
     env->ReleaseStringUTFChars(file, file8);
-    
+
     if (fd < 0) {
         //LOGW("Unable to open process file: %s\n", file8);
         return JNI_FALSE;
     }
-    
+
     char buffer[256];
     const int len = read(fd, buffer, sizeof(buffer)-1);
     close(fd);
-    
+
     if (len < 0) {
         //LOGW("Unable to open process file: %s fd=%d\n", file8, fd);
         return JNI_FALSE;
     }
     buffer[len] = 0;
-    
-    return android_os_Process_parseProcLineArray(env, clazz, buffer, 0, len, 
+
+    return android_os_Process_parseProcLineArray(env, clazz, buffer, 0, len,
             format, outStrings, outLongs, outFloats);
-    
+
 }
 
 void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz,
                                              jobject binderObject)
 {
     if (binderObject == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return;
     }
 
@@ -846,11 +846,11 @@
     struct timespec ts;
 
     int res = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
-    
+
     if (res != 0) {
         return (jlong) 0;
-    } 
-    
+    }
+
     nsecs_t when = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
     return (jlong) nanoseconds_to_milliseconds(when);
 }
diff --git a/core/jni/com_android_internal_graphics_NativeUtils.cpp b/core/jni/com_android_internal_graphics_NativeUtils.cpp
index 0829532..319946f 100644
--- a/core/jni/com_android_internal_graphics_NativeUtils.cpp
+++ b/core/jni/com_android_internal_graphics_NativeUtils.cpp
@@ -32,14 +32,14 @@
 static jclass class_fileDescriptor;
 static jfieldID field_fileDescriptor_descriptor;
 static jmethodID method_fileDescriptor_init;
- 
+
 
 static jboolean scrollRect(JNIEnv* env, jobject graphics2D, jobject canvas, jobject rect, int dx, int dy) {
     if (canvas == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        jniThrowNullPointerException(env, NULL);
         return false;
     }
-  
+
     SkIRect src, *srcPtr = NULL;
     if (NULL != rect) {
         GraphicsJNI::jrect_to_irect(env, rect, &src);
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index 52e8f42..e627e4a 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -94,7 +94,7 @@
     return ret;
 }
 
-static void com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv* env, 
+static void com_android_internal_os_ZygoteInit_reopenStdio(JNIEnv* env,
         jobject clazz, jobject in, jobject out, jobject errfd)
 {
     int fd;
@@ -131,7 +131,7 @@
     } while (err < 0 && errno == EINTR);
 }
 
-static void com_android_internal_os_ZygoteInit_closeDescriptor(JNIEnv* env, 
+static void com_android_internal_os_ZygoteInit_closeDescriptor(JNIEnv* env,
         jobject clazz, jobject descriptor)
 {
     int fd;
@@ -206,7 +206,7 @@
     capdata.effective = effective;
     capdata.permitted = permitted;
 
-    err = capset (&capheader, &capdata); 
+    err = capset (&capheader, &capdata);
 
     if (err < 0) {
         jniThrowIOException(env, errno);
@@ -231,7 +231,7 @@
     capheader.version = _LINUX_CAPABILITY_VERSION;
     capheader.pid = pid;
 
-    err = capget (&capheader, &capdata); 
+    err = capget (&capheader, &capdata);
 
     if (err < 0) {
         jniThrowIOException(env, errno);
@@ -243,11 +243,10 @@
 }
 
 static jint com_android_internal_os_ZygoteInit_selectReadable (
-        JNIEnv *env, jobject clazz, jobjectArray fds) 
+        JNIEnv *env, jobject clazz, jobjectArray fds)
 {
     if (fds == NULL) {
-        jniThrowException(env, "java/lang/NullPointerException",
-            "fds == null");
+        jniThrowNullPointerException(env, "fds == null");
         return -1;
     }
 
@@ -311,7 +310,7 @@
 }
 
 static jobject com_android_internal_os_ZygoteInit_createFileDescriptor (
-        JNIEnv *env, jobject clazz, jint fd) 
+        JNIEnv *env, jobject clazz, jint fd)
 {
     return jniCreateFileDescriptor(env, fd);
 }
@@ -329,17 +328,17 @@
       (void *) com_android_internal_os_ZygoteInit_setpgid },
     { "getpgid", "(I)I",
       (void *) com_android_internal_os_ZygoteInit_getpgid },
-    { "reopenStdio",   
+    { "reopenStdio",
         "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
-        "Ljava/io/FileDescriptor;)V", 
+        "Ljava/io/FileDescriptor;)V",
             (void *) com_android_internal_os_ZygoteInit_reopenStdio},
-    { "closeDescriptor", "(Ljava/io/FileDescriptor;)V", 
+    { "closeDescriptor", "(Ljava/io/FileDescriptor;)V",
         (void *) com_android_internal_os_ZygoteInit_closeDescriptor},
-    { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V", 
+    { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
         (void *)  com_android_internal_os_ZygoteInit_setCloseOnExec},
-    { "setCapabilities", "(JJ)V", 
+    { "setCapabilities", "(JJ)V",
         (void *) com_android_internal_os_ZygoteInit_setCapabilities },
-    { "capgetPermitted", "(I)J", 
+    { "capgetPermitted", "(I)J",
         (void *) com_android_internal_os_ZygoteInit_capgetPermitted },
     { "selectReadable", "([Ljava/io/FileDescriptor;)I",
         (void *) com_android_internal_os_ZygoteInit_selectReadable },
@@ -353,4 +352,3 @@
 }
 
 }; // namespace android
-