Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8451b25a authored by Elliott Hughes's avatar Elliott Hughes
Browse files

Use jniThrowException for exception throwing from native code.

I'll do media and the generated gl stuff separately. Otherwise, this
cleans up all direct calls of ThrowNew/Throw except the one in the
binder that needs to remain.

Change-Id: I8f95a5f020f53b25926ad31ac0c9477ddf85d04b
parent 62c1a92d
Loading
Loading
Loading
Loading
+21 −32
Original line number Diff line number Diff line
#define LOG_TAG "GraphicsJNI"

#include "jni.h"
#include "JNIHelp.h"
#include "GraphicsJNI.h"

#include "SkCanvas.h"
@@ -9,44 +10,32 @@
#include "SkRegion.h"
#include <android_runtime/AndroidRuntime.h>

void doThrow(JNIEnv* env, const char* exc, const char* msg) {
    // don't throw a new exception if we already have one pending
    if (env->ExceptionCheck() == JNI_FALSE) {
        jclass npeClazz;
        
        npeClazz = env->FindClass(exc);
        LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc);
        
        env->ThrowNew(npeClazz, msg);
    }
}

void doThrowNPE(JNIEnv* env) {
    doThrow(env, "java/lang/NullPointerException");
    jniThrowException(env, "java/lang/NullPointerException", NULL);
}

void doThrowAIOOBE(JNIEnv* env) {
    doThrow(env, "java/lang/ArrayIndexOutOfBoundsException");
    jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
}

void doThrowRE(JNIEnv* env, const char* msg) {
    doThrow(env, "java/lang/RuntimeException", msg);
    jniThrowException(env, "java/lang/RuntimeException", msg);
}

void doThrowIAE(JNIEnv* env, const char* msg) {
    doThrow(env, "java/lang/IllegalArgumentException", msg);
    jniThrowException(env, "java/lang/IllegalArgumentException", msg);
}

void doThrowISE(JNIEnv* env, const char* msg) {
    doThrow(env, "java/lang/IllegalStateException", msg);
    jniThrowException(env, "java/lang/IllegalStateException", msg);
}

void doThrowOOME(JNIEnv* env, const char* msg) {
    doThrow(env, "java/lang/OutOfMemoryError", msg);
    jniThrowException(env, "java/lang/OutOfMemoryError", msg);
}

void doThrowIOE(JNIEnv* env, const char* msg) {
    doThrow(env, "java/io/IOException", msg);
    jniThrowException(env, "java/io/IOException", msg);
}

bool GraphicsJNI::hasException(JNIEnv *env) {
@@ -508,7 +497,7 @@ jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
                                             SkColorTable* ctable) {
    Sk64 size64 = bitmap->getSize64();
    if (size64.isNeg() || !size64.is32()) {
        doThrow(env, "java/lang/IllegalArgumentException",
        jniThrowException(env, "java/lang/IllegalArgumentException",
                          "bitmap size exceeds 32bits");
        return NULL;
    }
+16 −17
Original line number Diff line number Diff line
@@ -232,7 +232,6 @@ private:
    int         fLen;
};

void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL);
void doThrowNPE(JNIEnv* env);
void doThrowAIOOBE(JNIEnv* env); // Array Index Out Of Bounds Exception
void doThrowIAE(JNIEnv* env, const char* msg = NULL);   // Illegal Argument
+4 −4
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ static jobject movie_decodeByteArray(JNIEnv* env, jobject clazz,

    int totalLength = env->GetArrayLength(byteArray);
    if ((offset | length) < 0 || offset + length > totalLength) {
        doThrow(env, "java/lang/ArrayIndexOutOfBoundsException");
        doThrowAIOOBE(env);
        return 0;
    }

+79 −79
Original line number Diff line number Diff line
@@ -327,7 +327,7 @@ public:
        size_t textLength = env->GetArrayLength(text);

        if ((index | count) < 0 || (size_t)(index + count) > textLength) {
            doThrow(env, "java/lang/ArrayIndexOutOfBoundsException");
            doThrowAIOOBE(env);
            return 0;
        }

@@ -351,7 +351,7 @@ public:

        int count = end - start;
        if ((start | count) < 0 || (size_t)count > textLength) {
            doThrow(env, "java/lang/IndexOutOfBoundsException");
            doThrowAIOOBE(env);
            return 0;
        }

@@ -667,7 +667,7 @@ public:
        }

        if ((index < 0) || (index + count > env->GetArrayLength(jtext))) {
            doThrow(env, "java/lang/ArrayIndexOutOfBoundsException");
            doThrowAIOOBE(env);
            return 0;
        }

+34 −45
Original line number Diff line number Diff line
@@ -14,7 +14,9 @@
 ** limitations under the License.
 */

#include <nativehelper/jni.h>
#include "jni.h"
#include "JNIHelp.h"

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
@@ -38,10 +40,6 @@

namespace android {

static jclass gIAEClass;
static jclass gUOEClass;
static jclass gAIOOBEClass;

static inline
void mx4transform(float x, float y, float z, float w, const float* pM, float* pDest) {
    pDest[0] = pM[0 + 4 * 0] * x + pM[0 + 4 * 1] * y + pM[0 + 4 * 2] * z + pM[0 + 4 * 3] * w;
@@ -151,6 +149,10 @@ int visibilityTest(float* pWS, float* pPositions, int positionsLength,
    return result;
}

static void doThrowIAE(JNIEnv* env, const char* msg) {
    jniThrowException(env, "java/lang/IllegalArgumentException", msg);
}

template<class JArray, class T>
class ArrayHelper {
public:
@@ -178,16 +180,16 @@ public:

    bool check() {
        if ( ! mRef) {
            mEnv->ThrowNew(gIAEClass, "array == null");
            doThrowIAE(mEnv, "array == null");
            return false;
        }
        if ( mOffset < 0) {
            mEnv->ThrowNew(gIAEClass, "offset < 0");
            doThrowIAE(mEnv, "offset < 0");
            return false;
        }
        mLength = mEnv->GetArrayLength(mRef) - mOffset;
        if (mLength < mMinSize ) {
            mEnv->ThrowNew(gIAEClass, "length - offset < n");
            doThrowIAE(mEnv, "length - offset < n");
            return false;
        }
        return true;
@@ -245,7 +247,7 @@ void util_computeBoundingSphere(JNIEnv *env, jclass clazz,
    sphere.bind();

    if ( positionsCount < 1 ) {
        env->ThrowNew(gIAEClass, "positionsCount < 1");
        doThrowIAE(env, "positionsCount < 1");
        return;
    }

@@ -450,8 +452,7 @@ int util_visibilityTest(JNIEnv *env, jclass clazz,
    }

    if (indices.mLength < indexCount) {
        env->ThrowNew(gIAEClass, "length < offset + indexCount");
        // Return value will be ignored, because an exception has been thrown.
        doThrowIAE(env, "length < offset + indexCount");
        return -1;
    }

@@ -784,11 +785,11 @@ public:
        if (mBuffer) {
            mData = getPointer(mEnv, mBuffer, &mRemaining);
            if (mData == NULL) {
                mEnv->ThrowNew(gIAEClass, errorMessage);
                doThrowIAE(mEnv, errorMessage);
            }
            return mData != NULL;
        } else {
            mEnv->ThrowNew(gIAEClass, errorMessage);
            doThrowIAE(mEnv, errorMessage);
            return false;
        }
    }
@@ -824,16 +825,16 @@ private:
static void etc1_encodeBlock(JNIEnv *env, jclass clazz,
        jobject in, jint validPixelMask, jobject out) {
    if (validPixelMask < 0 || validPixelMask > 15) {
        env->ThrowNew(gIAEClass, "validPixelMask");
        doThrowIAE(env, "validPixelMask");
        return;
    }
    BufferHelper inB(env, in);
    BufferHelper outB(env, out);
    if (inB.checkPointer("in") && outB.checkPointer("out")) {
        if (inB.remaining() < ETC1_DECODED_BLOCK_SIZE) {
            env->ThrowNew(gIAEClass, "in's remaining data < DECODED_BLOCK_SIZE");
            doThrowIAE(env, "in's remaining data < DECODED_BLOCK_SIZE");
        } else if (outB.remaining() < ETC1_ENCODED_BLOCK_SIZE) {
            env->ThrowNew(gIAEClass, "out's remaining data < ENCODED_BLOCK_SIZE");
            doThrowIAE(env, "out's remaining data < ENCODED_BLOCK_SIZE");
        } else {
            etc1_encode_block((etc1_byte*) inB.getData(), validPixelMask,
                    (etc1_byte*) outB.getData());
@@ -856,9 +857,9 @@ static void etc1_decodeBlock(JNIEnv *env, jclass clazz,
    BufferHelper outB(env, out);
    if (inB.checkPointer("in") && outB.checkPointer("out")) {
        if (inB.remaining() < ETC1_ENCODED_BLOCK_SIZE) {
            env->ThrowNew(gIAEClass, "in's remaining data < ENCODED_BLOCK_SIZE");
            doThrowIAE(env, "in's remaining data < ENCODED_BLOCK_SIZE");
        } else if (outB.remaining() < ETC1_DECODED_BLOCK_SIZE) {
            env->ThrowNew(gIAEClass, "out's remaining data < DECODED_BLOCK_SIZE");
            doThrowIAE(env, "out's remaining data < DECODED_BLOCK_SIZE");
        } else {
            etc1_decode_block((etc1_byte*) inB.getData(),
                    (etc1_byte*) outB.getData());
@@ -884,7 +885,7 @@ static void etc1_encodeImage(JNIEnv *env, jclass clazz,
        jobject in, jint width, jint height,
        jint pixelSize, jint stride, jobject out) {
    if (pixelSize < 2 || pixelSize > 3) {
        env->ThrowNew(gIAEClass, "pixelSize must be 2 or 3");
        doThrowIAE(env, "pixelSize must be 2 or 3");
        return;
    }
    BufferHelper inB(env, in);
@@ -893,9 +894,9 @@ static void etc1_encodeImage(JNIEnv *env, jclass clazz,
        jint imageSize = stride * height;
        jint encodedImageSize = etc1_get_encoded_data_size(width, height);
        if (inB.remaining() < imageSize) {
            env->ThrowNew(gIAEClass, "in's remaining data < image size");
            doThrowIAE(env, "in's remaining data < image size");
        } else if (outB.remaining() < encodedImageSize) {
            env->ThrowNew(gIAEClass, "out's remaining data < encoded image size");
            doThrowIAE(env, "out's remaining data < encoded image size");
        } else {
            int result = etc1_encode_image((etc1_byte*) inB.getData(),
                    width, height, pixelSize,
@@ -917,7 +918,7 @@ static void etc1_decodeImage(JNIEnv *env, jclass clazz,
        jint width, jint height,
        jint pixelSize, jint stride) {
    if (pixelSize < 2 || pixelSize > 3) {
        env->ThrowNew(gIAEClass, "pixelSize must be 2 or 3");
        doThrowIAE(env, "pixelSize must be 2 or 3");
        return;
    }
    BufferHelper inB(env, in);
@@ -926,9 +927,9 @@ static void etc1_decodeImage(JNIEnv *env, jclass clazz,
        jint imageSize = stride * height;
        jint encodedImageSize = etc1_get_encoded_data_size(width, height);
        if (inB.remaining() < encodedImageSize) {
            env->ThrowNew(gIAEClass, "in's remaining data < encoded image size");
            doThrowIAE(env, "in's remaining data < encoded image size");
        } else if (outB.remaining() < imageSize) {
            env->ThrowNew(gIAEClass, "out's remaining data < image size");
            doThrowIAE(env, "out's remaining data < image size");
        } else {
            int result = etc1_decode_image((etc1_byte*) inB.getData(),
                    (etc1_byte*) outB.getData(),
@@ -946,7 +947,7 @@ static void etc1_formatHeader(JNIEnv *env, jclass clazz,
    BufferHelper headerB(env, header);
    if (headerB.checkPointer("header") ){
        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
            env->ThrowNew(gIAEClass, "header's remaining data < ETC_PKM_HEADER_SIZE");
            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
        } else {
            etc1_pkm_format_header((etc1_byte*) headerB.getData(), width, height);
        }
@@ -962,7 +963,7 @@ static jboolean etc1_isValid(JNIEnv *env, jclass clazz,
    BufferHelper headerB(env, header);
    if (headerB.checkPointer("header") ){
        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
            env->ThrowNew(gIAEClass, "header's remaining data < ETC_PKM_HEADER_SIZE");
            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
        } else {
            result = etc1_pkm_is_valid((etc1_byte*) headerB.getData());
        }
@@ -979,7 +980,7 @@ static jint etc1_getWidth(JNIEnv *env, jclass clazz,
    BufferHelper headerB(env, header);
    if (headerB.checkPointer("header") ){
        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
            env->ThrowNew(gIAEClass, "header's remaining data < ETC_PKM_HEADER_SIZE");
            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
        } else {
            result = etc1_pkm_get_width((etc1_byte*) headerB.getData());
        }
@@ -996,7 +997,7 @@ static int etc1_getHeight(JNIEnv *env, jclass clazz,
    BufferHelper headerB(env, header);
    if (headerB.checkPointer("header") ){
        if (headerB.remaining() < ETC_PKM_HEADER_SIZE) {
            env->ThrowNew(gIAEClass, "header's remaining data < ETC_PKM_HEADER_SIZE");
            doThrowIAE(env, "header's remaining data < ETC_PKM_HEADER_SIZE");
        } else {
            result = etc1_pkm_get_height((etc1_byte*) headerB.getData());
        }
@@ -1008,22 +1009,12 @@ static int etc1_getHeight(JNIEnv *env, jclass clazz,
 * JNI registration
 */

static void
lookupClasses(JNIEnv* env) {
    gIAEClass = (jclass) env->NewGlobalRef(
            env->FindClass("java/lang/IllegalArgumentException"));
    gUOEClass = (jclass) env->NewGlobalRef(
            env->FindClass("java/lang/UnsupportedOperationException"));
    gAIOOBEClass = (jclass) env->NewGlobalRef(
            env->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
}

static JNINativeMethod gMatrixMethods[] = {
    { "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM },
    { "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV },
};

static JNINativeMethod gVisiblityMethods[] = {
static JNINativeMethod gVisibilityMethods[] = {
    { "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere },
    { "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres },
    { "visibilityTest", "([FI[FI[CII)I", (void*)util_visibilityTest },
@@ -1057,14 +1048,13 @@ typedef struct _ClassRegistrationInfo {

static ClassRegistrationInfo gClasses[] = {
    {"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)},
        {"android/opengl/Visibility", gVisiblityMethods, NELEM(gVisiblityMethods)},
    {"android/opengl/Visibility", gVisibilityMethods, NELEM(gVisibilityMethods)},
    {"android/opengl/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)},
    {"android/opengl/ETC1", gEtc1Methods, NELEM(gEtc1Methods)},
};

int register_android_opengl_classes(JNIEnv* env)
{
    lookupClasses(env);
    nativeClassInitBuffer(env);
    int result = 0;
    for (int i = 0; i < NELEM(gClasses); i++) {
@@ -1080,4 +1070,3 @@ int register_android_opengl_classes(JNIEnv* env)
}

} // namespace android
Loading