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

Commit fbb07884 authored by Elliott Hughes's avatar Elliott Hughes Committed by Android (Google) Code Review
Browse files

Merge "Use jniThrowException for exception throwing from native code."

parents 2915875f 8451b25a
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