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

Commit 8b1b0548 authored by James Dong's avatar James Dong Committed by Android (Google) Code Review
Browse files

Merge "Clean up JNI code"

parents 9de128ef 17524dc0
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -68,7 +68,21 @@ public class MediaMetadataRetriever
     * @param headers the headers to be sent together with the request for the data
     * @throws IllegalArgumentException If the URI is invalid.
     */
    public native void setDataSource(String uri, Map<String, String> headers)
    public void setDataSource(String uri,  Map<String, String> headers)
            throws IllegalArgumentException {
        int i = 0;
        String[] keys = new String[headers.size()];
        String[] values = new String[headers.size()];
        for (Map.Entry<String, String> entry: headers.entrySet()) {
            keys[i] = entry.getKey();
            values[i] = entry.getValue();
            ++i;
        }
        _setDataSource(uri, keys, values);
    }

    private native void _setDataSource(
        String uri, String[] keys, String[] values)
        throws IllegalArgumentException;

    /**
+17 −2
Original line number Diff line number Diff line
@@ -799,7 +799,22 @@ public class MediaPlayer
     * @throws IllegalStateException if it is called in an invalid state
     * @hide pending API council
     */
    public native void setDataSource(String path,  Map<String, String> headers)
    public void setDataSource(String path, Map<String, String> headers)
            throws IOException, IllegalArgumentException, IllegalStateException
    {
        int i = 0;
        String[] keys = new String[headers.size()];
        String[] values = new String[headers.size()];
        for (Map.Entry<String, String> entry: headers.entrySet()) {
            keys[i] = entry.getKey();
            values[i] = entry.getValue();
            ++i;
        }
        _setDataSource(path, keys, values);
    }

    private native void _setDataSource(
        String path, String[] keys, String[] values)
        throws IOException, IllegalArgumentException, IllegalStateException;

    /**
+36 −93
Original line number Diff line number Diff line
@@ -79,7 +79,9 @@ static void setRetriever(JNIEnv* env, jobject thiz, int retriever)

static void
android_media_MediaMetadataRetriever_setDataSourceAndHeaders(
        JNIEnv *env, jobject thiz, jstring path, jobject headers) {
        JNIEnv *env, jobject thiz, jstring path,
        jobjectArray keys, jobjectArray values) {

    LOGV("setDataSource");
    MediaMetadataRetriever* retriever = getRetriever(env, thiz);
    if (retriever == 0) {
@@ -103,10 +105,17 @@ android_media_MediaMetadataRetriever_setDataSourceAndHeaders(
    }

    String8 pathStr(tmp);

    env->ReleaseStringUTFChars(path, tmp);
    tmp = NULL;

    int nKeyValuePairs = env->GetArrayLength(keys);
    if (nKeyValuePairs != env->GetArrayLength(values)) {
        LOGE("keys and values have different length: %d <--> %d",
            nKeyValuePairs, env->GetArrayLength(values));
        jniThrowException(
                env, "java/lang/IllegalArgumentException", NULL);
        return;
    }
    // Don't let somebody trick us in to reading some random block of memory
    if (strncmp("mem://", pathStr.string(), 6) == 0) {
        jniThrowException(
@@ -114,110 +123,38 @@ android_media_MediaMetadataRetriever_setDataSourceAndHeaders(
        return;
    }

    // headers is a Map<String, String>.
    // We build a similar KeyedVector out of it.
    KeyedVector<String8, String8> headersVector;
    if (headers) {
        // Get the Map's entry Set.
        jclass mapClass = env->FindClass("java/util/Map");
        if (mapClass == NULL) {
            return;
        }

        jmethodID entrySet =
            env->GetMethodID(mapClass, "entrySet", "()Ljava/util/Set;");
        if (entrySet == NULL) {
            return;
        }

        jobject set = env->CallObjectMethod(headers, entrySet);
        if (set == NULL) {
            return;
        }

        // Obtain an iterator over the Set
        jclass setClass = env->FindClass("java/util/Set");
        if (setClass == NULL) {
            return;
        }

        jmethodID iterator =
            env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
        if (iterator == NULL) {
            return;
        }

        jobject iter = env->CallObjectMethod(set, iterator);
        if (iter == NULL) {
            return;
        }

        // Get the Iterator method IDs
        jclass iteratorClass = env->FindClass("java/util/Iterator");
        if (iteratorClass == NULL) {
            return;
        }
        jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
        if (hasNext == NULL) {
            return;
        }

        jmethodID next =
            env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
        if (next == NULL) {
            return;
        }

        // Get the Entry class method IDs
        jclass entryClass = env->FindClass("java/util/Map$Entry");
        if (entryClass == NULL) {
            return;
        }

        jmethodID getKey =
            env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
        if (getKey == NULL) {
            return;
        }

        jmethodID getValue =
            env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
        if (getValue == NULL) {
            return;
        }

        // Iterate over the entry Set
        while (env->CallBooleanMethod(iter, hasNext)) {
            jobject entry = env->CallObjectMethod(iter, next);
            jstring key = (jstring) env->CallObjectMethod(entry, getKey);
            jstring value = (jstring) env->CallObjectMethod(entry, getValue);
    for (int i = 0; i < nKeyValuePairs; ++i) {
        // No need to check on the ArrayIndexOutOfBoundsException, since
        // it won't happen here.
        jstring key = (jstring) env->GetObjectArrayElement(keys, i);
        jstring value = (jstring) env->GetObjectArrayElement(values, i);

        const char* keyStr = env->GetStringUTFChars(key, NULL);
            if (!keyStr) {  // Out of memory
        if (!keyStr) {  // OutOfMemoryError
            return;
        }

        const char* valueStr = env->GetStringUTFChars(value, NULL);
            if (!valueStr) {  // Out of memory
        if (!valueStr) {  // OutOfMemoryError
            env->ReleaseStringUTFChars(key, keyStr);
            return;
        }

        headersVector.add(String8(keyStr), String8(valueStr));

            env->DeleteLocalRef(entry);
        env->ReleaseStringUTFChars(key, keyStr);
            env->DeleteLocalRef(key);
        env->ReleaseStringUTFChars(value, valueStr);
        env->DeleteLocalRef(key);
        env->DeleteLocalRef(value);
        }

    }

    process_media_retriever_call(
            env,
            retriever->setDataSource(
                pathStr.string(), headers ? &headersVector : NULL),
                pathStr.string(), nKeyValuePairs > 0 ? &headersVector : NULL),

            "java/lang/RuntimeException",
            "setDataSource failed");
@@ -226,7 +163,7 @@ android_media_MediaMetadataRetriever_setDataSourceAndHeaders(
static void android_media_MediaMetadataRetriever_setDataSource(
        JNIEnv *env, jobject thiz, jstring path) {
    android_media_MediaMetadataRetriever_setDataSourceAndHeaders(
            env, thiz, path, NULL);
            env, thiz, path, NULL, NULL);
}

static void android_media_MediaMetadataRetriever_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
@@ -539,7 +476,13 @@ static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobje
// JNI mapping between Java methods and native methods
static JNINativeMethod nativeMethods[] = {
        {"setDataSource",   "(Ljava/lang/String;)V", (void *)android_media_MediaMetadataRetriever_setDataSource},
        {"setDataSource",   "(Ljava/lang/String;Ljava/util/Map;)V", (void *)android_media_MediaMetadataRetriever_setDataSourceAndHeaders},

        {
            "_setDataSource",
            "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
            (void *)android_media_MediaMetadataRetriever_setDataSourceAndHeaders
        },

        {"setDataSource",   "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaMetadataRetriever_setDataSourceFD},
        {"_getFrameAtTime", "(JI)Landroid/graphics/Bitmap;", (void *)android_media_MediaMetadataRetriever_getFrameAtTime},
        {"extractMetadata", "(I)Ljava/lang/String;", (void *)android_media_MediaMetadataRetriever_extractMetadata},
+37 −95
Original line number Diff line number Diff line
@@ -186,7 +186,9 @@ static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStat

static void
android_media_MediaPlayer_setDataSourceAndHeaders(
        JNIEnv *env, jobject thiz, jstring path, jobject headers) {
        JNIEnv *env, jobject thiz, jstring path,
        jobjectArray keys, jobjectArray values) {

    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    if (mp == NULL ) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -207,112 +209,46 @@ android_media_MediaPlayer_setDataSourceAndHeaders(
    env->ReleaseStringUTFChars(path, tmp);
    tmp = NULL;

    // headers is a Map<String, String>.
    // We build a similar KeyedVector out of it.
    KeyedVector<String8, String8> headersVector;
    if (headers) {
        // Get the Map's entry Set.
        jclass mapClass = env->FindClass("java/util/Map");
        if (mapClass == NULL) {
            return;
        }

        jmethodID entrySet =
            env->GetMethodID(mapClass, "entrySet", "()Ljava/util/Set;");
        if (entrySet == NULL) {
            return;
        }

        jobject set = env->CallObjectMethod(headers, entrySet);
        if (set == NULL) {
            return;
        }

        // Obtain an iterator over the Set
        jclass setClass = env->FindClass("java/util/Set");
        if (setClass == NULL) {
            return;
        }

        jmethodID iterator =
            env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
        if (iterator == NULL) {
            return;
        }

        jobject iter = env->CallObjectMethod(set, iterator);
        if (iter == NULL) {
            return;
        }

        // Get the Iterator method IDs
        jclass iteratorClass = env->FindClass("java/util/Iterator");
        if (iteratorClass == NULL) {
            return;
        }

        jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
        if (hasNext == NULL) {
            return;
        }

        jmethodID next =
            env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
        if (next == NULL) {
            return;
        }

        // Get the Entry class method IDs
        jclass entryClass = env->FindClass("java/util/Map$Entry");
        if (entryClass == NULL) {
            return;
        }

        jmethodID getKey =
            env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
        if (getKey == NULL) {
            return;
        }

        jmethodID getValue =
            env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
        if (getValue == NULL) {
    int nKeyValuePairs = env->GetArrayLength(keys);
    if (nKeyValuePairs != env->GetArrayLength(values)) {
        LOGE("keys and values have different length: %d <-> %d",
            nKeyValuePairs, env->GetArrayLength(values));
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
        return;
    }

        // Iterate over the entry Set
        while (env->CallBooleanMethod(iter, hasNext)) {
            jobject entry = env->CallObjectMethod(iter, next);
            jstring key = (jstring) env->CallObjectMethod(entry, getKey);
            jstring value = (jstring) env->CallObjectMethod(entry, getValue);
    // We build a KeyedVector out of the key and val arrays
    KeyedVector<String8, String8> headersVector;
    for (int i = 0; i < nKeyValuePairs; ++i) {
        // No need to check ArrayIndexOutOfBoundsException, since we
        // know it won't happen here.
        jstring key = (jstring) env->GetObjectArrayElement(keys, i);
        jstring val = (jstring) env->GetObjectArrayElement(values, i);

        const char* keyStr = env->GetStringUTFChars(key, NULL);
            if (!keyStr) {  // Out of memory
        if (!keyStr) {  // OutOfMemoryError
            return;
        }

            const char* valueStr = env->GetStringUTFChars(value, NULL);
            if (!valueStr) {  // Out of memory
        const char* valueStr = env->GetStringUTFChars(val, NULL);
        if (!valueStr) {  // OutOfMemoryError
            env->ReleaseStringUTFChars(key, keyStr);
            return;
        }

        headersVector.add(String8(keyStr), String8(valueStr));

            env->DeleteLocalRef(entry);
        env->ReleaseStringUTFChars(key, keyStr);
        env->ReleaseStringUTFChars(val, valueStr);
        env->DeleteLocalRef(key);
            env->ReleaseStringUTFChars(value, valueStr);
            env->DeleteLocalRef(value);
        }

        env->DeleteLocalRef(val);
    }

    LOGV("setDataSource: path %s", pathStr);
    status_t opStatus =
        mp->setDataSource(
                pathStr,
                headers ? &headersVector : NULL);
                nKeyValuePairs > 0? &headersVector : NULL);

    process_media_player_call(
            env, thiz, opStatus, "java/io/IOException",
@@ -322,7 +258,7 @@ android_media_MediaPlayer_setDataSourceAndHeaders(
static void
android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path)
{
    android_media_MediaPlayer_setDataSourceAndHeaders(env, thiz, path, 0);
    android_media_MediaPlayer_setDataSourceAndHeaders(env, thiz, path, NULL, NULL);
}

static void
@@ -851,7 +787,13 @@ android_media_MediaPlayer_getParameter(JNIEnv *env, jobject thiz, jint key, jobj

static JNINativeMethod gMethods[] = {
    {"setDataSource",       "(Ljava/lang/String;)V",            (void *)android_media_MediaPlayer_setDataSource},
    {"setDataSource",       "(Ljava/lang/String;Ljava/util/Map;)V",(void *)android_media_MediaPlayer_setDataSourceAndHeaders},

    {
        "_setDataSource",
        "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
        (void *)android_media_MediaPlayer_setDataSourceAndHeaders
    },

    {"setDataSource",       "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD},
    {"_setVideoSurfaceOrSurfaceTexture", "()V",                 (void *)android_media_MediaPlayer_setVideoSurfaceOrSurfaceTexture},
    {"prepare",             "()V",                              (void *)android_media_MediaPlayer_prepare},