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 Original line Diff line number Diff line
#define LOG_TAG "GraphicsJNI"
#define LOG_TAG "GraphicsJNI"


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


#include "SkCanvas.h"
#include "SkCanvas.h"
@@ -9,44 +10,32 @@
#include "SkRegion.h"
#include "SkRegion.h"
#include <android_runtime/AndroidRuntime.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) {
void doThrowNPE(JNIEnv* env) {
    doThrow(env, "java/lang/NullPointerException");
    jniThrowException(env, "java/lang/NullPointerException", NULL);
}
}


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


void doThrowRE(JNIEnv* env, const char* msg) {
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) {
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) {
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) {
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) {
void doThrowIOE(JNIEnv* env, const char* msg) {
    doThrow(env, "java/io/IOException", msg);
    jniThrowException(env, "java/io/IOException", msg);
}
}


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


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


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


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


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


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


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


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


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


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


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

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


namespace android {
namespace android {


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

static inline
static inline
void mx4transform(float x, float y, float z, float w, const float* pM, float* pDest) {
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;
    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;
    return result;
}
}


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

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


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


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


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


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


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


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


static ClassRegistrationInfo gClasses[] = {
static ClassRegistrationInfo gClasses[] = {
    {"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)},
    {"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/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)},
    {"android/opengl/ETC1", gEtc1Methods, NELEM(gEtc1Methods)},
    {"android/opengl/ETC1", gEtc1Methods, NELEM(gEtc1Methods)},
};
};


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


} // namespace android
} // namespace android
Loading