android_media_Utils.cpp revision 5c850396b39a57baabd37a9c0c8324f1bee408ca
179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong/*
279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * Copyright 2011, The Android Open Source Project
379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong *
479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * Licensed under the Apache License, Version 2.0 (the "License");
579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * you may not use this file except in compliance with the License.
679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * You may obtain a copy of the License at
779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong *
879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong *     http://www.apache.org/licenses/LICENSE-2.0
979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong *
1079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * Unless required by applicable law or agreed to in writing, software
1179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * distributed under the License is distributed on an "AS IS" BASIS,
1279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * See the License for the specific language governing permissions and
1479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong * limitations under the License.
1579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong */
1679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
1779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong// #define LOG_NDEBUG 0
1879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong#define LOG_TAG "AndroidMediaUtils"
1979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
2079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong#include <utils/Log.h>
2179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong#include "android_media_Utils.h"
2279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
2388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
2488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
2588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
2688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dongnamespace android {
2879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
2979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dongbool ConvertKeyValueArraysToKeyedVector(
3079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        JNIEnv *env, jobjectArray keys, jobjectArray values,
3179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        KeyedVector<String8, String8>* keyedVector) {
3279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
3379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    int nKeyValuePairs = 0;
3479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    bool failed = false;
3579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    if (keys != NULL && values != NULL) {
3679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        nKeyValuePairs = env->GetArrayLength(keys);
3779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        failed = (nKeyValuePairs != env->GetArrayLength(values));
3879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
3979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
4079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    if (!failed) {
4179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        failed = ((keys != NULL && values == NULL) ||
4279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong                  (keys == NULL && values != NULL));
4379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
4479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
4579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    if (failed) {
463762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("keys and values arrays have different length");
4779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
4879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        return false;
4979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
5079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
5179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    for (int i = 0; i < nKeyValuePairs; ++i) {
5279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        // No need to check on the ArrayIndexOutOfBoundsException, since
5379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        // it won't happen here.
5479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        jstring key = (jstring) env->GetObjectArrayElement(keys, i);
5579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        jstring value = (jstring) env->GetObjectArrayElement(values, i);
5679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
5779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        const char* keyStr = env->GetStringUTFChars(key, NULL);
5879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        if (!keyStr) {  // OutOfMemoryError
5979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong            return false;
6079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        }
6179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
6279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        const char* valueStr = env->GetStringUTFChars(value, NULL);
6379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        if (!valueStr) {  // OutOfMemoryError
6479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong            env->ReleaseStringUTFChars(key, keyStr);
6579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong            return false;
6679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        }
6779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
6879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        keyedVector->add(String8(keyStr), String8(valueStr));
6979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
7079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->ReleaseStringUTFChars(key, keyStr);
7179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->ReleaseStringUTFChars(value, valueStr);
7279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->DeleteLocalRef(key);
7379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->DeleteLocalRef(value);
7479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
7579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    return true;
7679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong}
7779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
7888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeIntegerObject(JNIEnv *env, int32_t value) {
7988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("java/lang/Integer");
8088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
8188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID integerConstructID = env->GetMethodID(clazz, "<init>", "(I)V");
8388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(integerConstructID != NULL);
8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return env->NewObject(clazz, integerConstructID, value);
8688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeFloatObject(JNIEnv *env, float value) {
8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("java/lang/Float");
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID floatConstructID = env->GetMethodID(clazz, "<init>", "(F)V");
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(floatConstructID != NULL);
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return env->NewObject(clazz, floatConstructID, value);
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeByteBufferObject(
9988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, const void *data, size_t size) {
10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jbyteArray byteArrayObj = env->NewByteArray(size);
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->SetByteArrayRegion(byteArrayObj, 0, size, (const jbyte *)data);
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("java/nio/ByteBuffer");
10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
10588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID byteBufWrapID =
10788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->GetStaticMethodID(clazz, "wrap", "([B)Ljava/nio/ByteBuffer;");
10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(byteBufWrapID != NULL);
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject byteBufObj = env->CallStaticObjectMethod(
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            clazz, byteBufWrapID, byteArrayObj);
11288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteLocalRef(byteArrayObj); byteArrayObj = NULL;
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return byteBufObj;
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t ConvertMessageToMap(
11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, const sp<AMessage> &msg, jobject *map) {
12088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass hashMapClazz = env->FindClass("java/util/HashMap");
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapClazz == NULL) {
12388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
12488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
12588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID hashMapConstructID =
12788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->GetMethodID(hashMapClazz, "<init>", "()V");
12888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapConstructID == NULL) {
13088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
13188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
13288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID hashMapPutID =
13488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->GetMethodID(
13588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                hashMapClazz,
13688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "put",
13788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
13888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapPutID == NULL) {
14088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
14188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
14288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject hashMap = env->NewObject(hashMapClazz, hashMapConstructID);
14488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < msg->countEntries(); ++i) {
14688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        AMessage::Type valueType;
14788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *key = msg->getEntryNameAt(i, &valueType);
14888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject valueObj = NULL;
15088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        switch (valueType) {
15288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeInt32:
15388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
15488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                int32_t val;
15588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findInt32(key, &val));
15688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeIntegerObject(env, val);
15888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
15988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
16088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeFloat:
16288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
16388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                float val;
16488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findFloat(key, &val));
16588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeFloatObject(env, val);
16788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
16888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
16988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeString:
17188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
17288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                AString val;
17388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findString(key, &val));
17488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = env->NewStringUTF(val.c_str());
17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1795c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber            case AMessage::kTypeBuffer:
18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
1815c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber                sp<ABuffer> buffer;
1825c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber                CHECK(msg->findBuffer(key, &buffer));
18388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeByteBufferObject(
18588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        env, buffer->data(), buffer->size());
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
18788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            default:
19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
19188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
19288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (valueObj != NULL) {
19488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jstring keyObj = env->NewStringUTF(key);
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jobject res = env->CallObjectMethod(
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    hashMap, hashMapPutID, keyObj, valueObj);
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->DeleteLocalRef(keyObj); keyObj = NULL;
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->DeleteLocalRef(valueObj); valueObj = NULL;
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
20388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *map = hashMap;
20588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
20788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
20888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t ConvertKeyValueArraysToMessage(
21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobjectArray keys, jobjectArray values,
21188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        sp<AMessage> *out) {
21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass stringClass = env->FindClass("java/lang/String");
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(stringClass != NULL);
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass integerClass = env->FindClass("java/lang/Integer");
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(integerClass != NULL);
21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass floatClass = env->FindClass("java/lang/Float");
21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(floatClass != NULL);
22088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass byteBufClass = env->FindClass("java/nio/ByteBuffer");
22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(byteBufClass != NULL);
22388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg = new AMessage;
22588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jsize numEntries = 0;
22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (keys != NULL) {
22988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (values == NULL) {
23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
23288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        numEntries = env->GetArrayLength(keys);
23488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (numEntries != env->GetArrayLength(values)) {
23688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
23788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
23888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (values != NULL) {
23988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
24088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
24188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (jsize i = 0; i < numEntries; ++i) {
24388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject keyObj = env->GetObjectArrayElement(keys, i);
24488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (!env->IsInstanceOf(keyObj, stringClass)) {
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
24788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
24888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *tmp = env->GetStringUTFChars((jstring)keyObj, NULL);
25088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (tmp == NULL) {
25288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -ENOMEM;
25388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
25488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        AString key = tmp;
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->ReleaseStringUTFChars((jstring)keyObj, tmp);
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        tmp = NULL;
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject valueObj = env->GetObjectArrayElement(values, i);
26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (env->IsInstanceOf(valueObj, stringClass)) {
26388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            const char *value = env->GetStringUTFChars((jstring)valueObj, NULL);
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            if (value == NULL) {
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                return -ENOMEM;
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setString(key.c_str(), value);
27088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->ReleaseStringUTFChars((jstring)valueObj, value);
27288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            value = NULL;
27388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else if (env->IsInstanceOf(valueObj, integerClass)) {
27488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID intValueID =
27588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetMethodID(integerClass, "intValue", "()I");
27688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(intValueID != NULL);
27788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint value = env->CallIntMethod(valueObj, intValueID);
27988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setInt32(key.c_str(), value);
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else if (env->IsInstanceOf(valueObj, floatClass)) {
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID floatValueID =
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetMethodID(floatClass, "floatValue", "()F");
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(floatValueID != NULL);
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jfloat value = env->CallFloatMethod(valueObj, floatValueID);
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setFloat(key.c_str(), value);
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else if (env->IsInstanceOf(valueObj, byteBufClass)) {
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID positionID =
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetMethodID(byteBufClass, "position", "()I");
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(positionID != NULL);
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID limitID =
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetMethodID(byteBufClass, "limit", "()I");
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(limitID != NULL);
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint position = env->CallIntMethod(valueObj, positionID);
29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint limit = env->CallIntMethod(valueObj, limitID);
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            sp<ABuffer> buffer = new ABuffer(limit - position);
30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            void *data = env->GetDirectBufferAddress(valueObj);
30488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            if (data != NULL) {
30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                memcpy(buffer->data(),
30788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                       (const uint8_t *)data + position,
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                       buffer->size());
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            } else {
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                jmethodID arrayID =
31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env->GetMethodID(byteBufClass, "array", "()[B");
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(arrayID != NULL);
31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                jbyteArray byteArray =
31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    (jbyteArray)env->CallObjectMethod(valueObj, arrayID);
31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(byteArray != NULL);
31788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetByteArrayRegion(
31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        byteArray,
32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        position,
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        buffer->size(),
32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        (jbyte *)buffer->data());
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->DeleteLocalRef(byteArray); byteArray = NULL;
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setObject(key.c_str(), buffer);
32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *out = msg;
33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong}  // namespace android
33779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
338