Fix for 512 limit in assetManager.list

Also replaced all doThrow by jniThrow.

OutOfMemory after string creation were removed: should have been thrown before.

Bug http://b/issue?id=2949164

Change-Id: Idea8e27fdedeb43e3976776c477766e4dcdebcf8
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index b7d0c67..6d80cc4 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -66,16 +66,6 @@
 
 // ----------------------------------------------------------------------------
 
-static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
-{
-    jclass npeClazz;
-
-    npeClazz = env->FindClass(exc);
-    LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc);
-
-    env->ThrowNew(npeClazz, msg);
-}
-
 enum {
     STYLE_NUM_ENTRIES = 6,
     STYLE_TYPE = 0,
@@ -131,14 +121,14 @@
 
     LOGV("openAsset in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL || am == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+    if (fileName == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "fileName");
         return -1;
     }
 
     if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
         && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
-        doThrow(env, "java/lang/IllegalArgumentException");
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
         return -1;
     }
 
@@ -146,7 +136,7 @@
     Asset* a = am->open(fileName8, (Asset::AccessMode)mode);
 
     if (a == NULL) {
-        doThrow(env, "java/io/FileNotFoundException", fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
         env->ReleaseStringUTFChars(fileName, fileName8);
         return -1;
     }
@@ -164,7 +154,7 @@
     delete a;
     
     if (fd < 0) {
-        doThrow(env, "java/io/FileNotFoundException",
+        jniThrowException(env, "java/io/FileNotFoundException",
                 "This file can not be opened as a file descriptor; it is probably compressed");
         return NULL;
     }
@@ -199,8 +189,8 @@
 
     LOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL || am == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+    if (fileName == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "fileName");
         return NULL;
     }
 
@@ -208,7 +198,7 @@
     Asset* a = am->open(fileName8, Asset::ACCESS_RANDOM);
 
     if (a == NULL) {
-        doThrow(env, "java/io/FileNotFoundException", fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
         env->ReleaseStringUTFChars(fileName, fileName8);
         return NULL;
     }
@@ -231,14 +221,14 @@
 
     LOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL || am == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+    if (fileName == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "fileName");
         return -1;
     }
 
     if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
         && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
-        doThrow(env, "java/lang/IllegalArgumentException");
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
         return -1;
     }
 
@@ -248,7 +238,7 @@
         : am->openNonAsset(fileName8, (Asset::AccessMode)mode);
 
     if (a == NULL) {
-        doThrow(env, "java/io/FileNotFoundException", fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
         env->ReleaseStringUTFChars(fileName, fileName8);
         return -1;
     }
@@ -271,8 +261,8 @@
 
     LOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL || am == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+    if (fileName == NULL ) {
+        jniThrowException(env, "java/lang/NullPointerException", "fileName");
         return NULL;
     }
 
@@ -282,7 +272,7 @@
         : am->openNonAsset(fileName8, Asset::ACCESS_RANDOM);
 
     if (a == NULL) {
-        doThrow(env, "java/io/FileNotFoundException", fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
         env->ReleaseStringUTFChars(fileName, fileName8);
         return NULL;
     }
@@ -301,8 +291,8 @@
         return NULL;
     }
 
-    if (fileName == NULL || am == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+    if (fileName == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "fileName");
         return NULL;
     }
 
@@ -313,7 +303,7 @@
     env->ReleaseStringUTFChars(fileName, fileName8);
 
     if (dir == NULL) {
-        doThrow(env, "java/io/FileNotFoundException", fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
         return NULL;
     }
 
@@ -329,7 +319,6 @@
     jobjectArray array = env->NewObjectArray(dir->getFileCount(),
                                                 cls, NULL);
     if (array == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
         delete dir;
         return NULL;
     }
@@ -338,11 +327,11 @@
         const String8& name = dir->getFileName(i);
         jstring str = env->NewStringUTF(name.string());
         if (str == NULL) {
-            doThrow(env, "java/lang/OutOfMemoryError");
             delete dir;
             return NULL;
         }
         env->SetObjectArrayElement(array, i, str);
+        env->DeleteLocalRef(str);
     }
 
     delete dir;
@@ -358,7 +347,7 @@
     //printf("Destroying Asset Stream: %p\n", a);
 
     if (a == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "asset");
         return;
     }
 
@@ -371,7 +360,7 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "asset");
         return -1;
     }
 
@@ -387,7 +376,7 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL || bArray == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "asset");
         return -1;
     }
 
@@ -397,7 +386,7 @@
     
     jsize bLen = env->GetArrayLength(bArray);
     if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
-        doThrow(env, "java/lang/IndexOutOfBoundsException");
+        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
         return -1;
     }
 
@@ -408,7 +397,7 @@
     if (res > 0) return res;
 
     if (res < 0) {
-        doThrow(env, "java/io/IOException");
+        jniThrowException(env, "java/io/IOException", "");
     }
     return -1;
 }
@@ -420,7 +409,7 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "asset");
         return -1;
     }
 
@@ -434,7 +423,7 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "asset");
         return -1;
     }
 
@@ -447,7 +436,7 @@
     Asset* a = (Asset*)asset;
 
     if (a == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "asset");
         return -1;
     }
 
@@ -458,7 +447,7 @@
                                                        jstring path)
 {
     if (path == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "path");
         return JNI_FALSE;
     }
 
@@ -490,7 +479,7 @@
                                                 jstring locale)
 {
     if (locale == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "locale");
         return;
     }
 
@@ -525,7 +514,12 @@
     }
 
     for (int i=0; i<N; i++) {
-        env->SetObjectArrayElement(result, i, env->NewStringUTF(locales[i].string()));
+        jstring str = env->NewStringUTF(locales[i].string())
+        if (str == NULL) {
+            return NULL;
+        }
+        env->SetObjectArrayElement(result, i, str);
+        env->DeleteLocalRef(str);
     }
 
     return result;
@@ -576,7 +570,7 @@
                                                             jstring defPackage)
 {
     if (name == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "name");
         return 0;
     }
 
@@ -814,14 +808,10 @@
     }
     String8 name(am->getAssetPath((void*)cookie));
     if (name.length() == 0) {
-        doThrow(env, "java/lang/IndexOutOfBoundsException");
+        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
         return NULL;
     }
     jstring str = env->NewStringUTF(name.string());
-    if (str == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
-        return NULL;
-    }
     return str;
 }
 
@@ -889,7 +879,7 @@
     const ResTable& res(theme->getResTable());
     
     if (tag == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "tag");
         return;
     }
     
@@ -917,8 +907,16 @@
                                                         jintArray outValues,
                                                         jintArray outIndices)
 {
-    if (themeToken == 0 || attrs == NULL || outValues == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+    if (themeToken == 0) {
+        jniThrowException(env, "java/lang/NullPointerException", "theme token");
+        return JNI_FALSE;
+    }
+    if (attrs == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "attrs");
+        return JNI_FALSE;
+    }
+    if (outValues == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "out values");
         return JNI_FALSE;
     }
 
@@ -934,13 +932,13 @@
     const jsize NI = env->GetArrayLength(attrs);
     const jsize NV = env->GetArrayLength(outValues);
     if (NV < (NI*STYLE_NUM_ENTRIES)) {
-        doThrow(env, "java/lang/IndexOutOfBoundsException");
+        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
         return JNI_FALSE;
     }
 
     jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
     if (src == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
 
@@ -948,7 +946,7 @@
     jint* dest = baseDest;
     if (dest == NULL) {
         env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-        doThrow(env, "java/lang/OutOfMemoryError");
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
 
@@ -1152,8 +1150,16 @@
                                                         jintArray outValues,
                                                         jintArray outIndices)
 {
-    if (xmlParserToken == 0 || attrs == NULL || outValues == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+    if (xmlParserToken == 0) {
+        jniThrowException(env, "java/lang/NullPointerException", "xmlParserToken");
+        return JNI_FALSE;
+    }
+    if (attrs == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "attrs");
+        return JNI_FALSE;
+    }
+    if (outValues == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "out values");
         return JNI_FALSE;
     }
     
@@ -1169,13 +1175,13 @@
     const jsize NI = env->GetArrayLength(attrs);
     const jsize NV = env->GetArrayLength(outValues);
     if (NV < (NI*STYLE_NUM_ENTRIES)) {
-        doThrow(env, "java/lang/IndexOutOfBoundsException");
+        jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
         return JNI_FALSE;
     }
     
     jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
     if (src == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
     
@@ -1183,7 +1189,7 @@
     jint* dest = baseDest;
     if (dest == NULL) {
         env->ReleasePrimitiveArrayCritical(attrs, src, 0);
-        doThrow(env, "java/lang/OutOfMemoryError");
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
     
@@ -1306,7 +1312,7 @@
                                                         jintArray outValues)
 {
     if (outValues == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+        jniThrowException(env, "java/lang/NullPointerException", "out values");
         return JNI_FALSE;
     }
     
@@ -1324,7 +1330,7 @@
     jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
     jint* dest = baseDest;
     if (dest == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return JNI_FALSE;
     }
     
@@ -1399,8 +1405,8 @@
 
     LOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
 
-    if (fileName == NULL || am == NULL) {
-        doThrow(env, "java/lang/NullPointerException");
+    if (fileName == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "fileName");
         return 0;
     }
 
@@ -1410,7 +1416,7 @@
         : am->openNonAsset(fileName8, Asset::ACCESS_BUFFER);
 
     if (a == NULL) {
-        doThrow(env, "java/io/FileNotFoundException", fileName8);
+        jniThrowException(env, "java/io/FileNotFoundException", fileName8);
         env->ReleaseStringUTFChars(fileName, fileName8);
         return 0;
     }
@@ -1422,7 +1428,7 @@
     delete a;
 
     if (err != NO_ERROR) {
-        doThrow(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
+        jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
         return 0;
     }
 
@@ -1446,7 +1452,7 @@
 
     jintArray array = env->NewIntArray(N * 2);
     if (array == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         res.unlockBag(startOfBag);
         return NULL;
     }
@@ -1540,13 +1546,12 @@
                 res.unlockBag(startOfBag);
                 return NULL;
             }
-        }
 
-        env->SetObjectArrayElement(array, i, str);
+            env->SetObjectArrayElement(array, i, str);
 
-        // If we have a large amount of strings in our array, we might
-        // overflow the local reference table of the VM.
-        if (str != NULL) {
+            // str is not NULL at that point, otherwise ExceptionCheck would have been true.
+            // If we have a large amount of strings in our array, we might
+            // overflow the local reference table of the VM.
             env->DeleteLocalRef(str);
         }
     }
@@ -1571,7 +1576,7 @@
 
     jintArray array = env->NewIntArray(N);
     if (array == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         res.unlockBag(startOfBag);
         return NULL;
     }
@@ -1603,7 +1608,7 @@
 {
     AssetManager* am = new AssetManager();
     if (am == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
+        jniThrowException(env, "java/lang/OutOfMemoryError", "");
         return;
     }
 
@@ -1637,11 +1642,6 @@
     }
     
     jstring str = env->NewStringUTF(alloc.string());
-    if (str == NULL) {
-        doThrow(env, "java/lang/OutOfMemoryError");
-        return NULL;
-    }
-    
     return str;
 }