android_media_Utils.cpp revision 8f7a8f1eba590f4a0bb21988fc2a876dcb72dccd
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
278d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber#include <nativehelper/ScopedLocalRef.h>
288d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
2979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dongnamespace android {
3079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
318409c0691fb128fef6244305977342776bddf919Jaesung ChungFileStream::FileStream(const String8 filename)
328409c0691fb128fef6244305977342776bddf919Jaesung Chung    : mPosition(0),
338409c0691fb128fef6244305977342776bddf919Jaesung Chung      mSize(0) {
348409c0691fb128fef6244305977342776bddf919Jaesung Chung    mFile = fopen(filename.string(), "r");
358409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (mFile == NULL) {
368409c0691fb128fef6244305977342776bddf919Jaesung Chung        return;
378409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
388409c0691fb128fef6244305977342776bddf919Jaesung Chung    // Get the size.
398409c0691fb128fef6244305977342776bddf919Jaesung Chung    fseek(mFile, 0l, SEEK_END);
408409c0691fb128fef6244305977342776bddf919Jaesung Chung    mSize = ftell(mFile);
418409c0691fb128fef6244305977342776bddf919Jaesung Chung    fseek(mFile, 0l, SEEK_SET);
428409c0691fb128fef6244305977342776bddf919Jaesung Chung}
438409c0691fb128fef6244305977342776bddf919Jaesung Chung
448409c0691fb128fef6244305977342776bddf919Jaesung ChungFileStream::~FileStream() {
458409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (mFile != NULL) {
468409c0691fb128fef6244305977342776bddf919Jaesung Chung        fclose(mFile);
478409c0691fb128fef6244305977342776bddf919Jaesung Chung        mFile = NULL;
488409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
498409c0691fb128fef6244305977342776bddf919Jaesung Chung}
508409c0691fb128fef6244305977342776bddf919Jaesung Chung
518409c0691fb128fef6244305977342776bddf919Jaesung Chungpiex::Error FileStream::GetData(
528409c0691fb128fef6244305977342776bddf919Jaesung Chung        const size_t offset, const size_t length, std::uint8_t* data) {
538409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (mFile == NULL) {
548409c0691fb128fef6244305977342776bddf919Jaesung Chung        return piex::Error::kFail;
558409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
568409c0691fb128fef6244305977342776bddf919Jaesung Chung
578409c0691fb128fef6244305977342776bddf919Jaesung Chung    // Seek first.
588409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (mPosition != offset) {
598409c0691fb128fef6244305977342776bddf919Jaesung Chung        fseek(mFile, offset, SEEK_SET);
608409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
618409c0691fb128fef6244305977342776bddf919Jaesung Chung
628409c0691fb128fef6244305977342776bddf919Jaesung Chung    // Read bytes.
638409c0691fb128fef6244305977342776bddf919Jaesung Chung    size_t size = fread((void*)data, sizeof(std::uint8_t), length, mFile);
648409c0691fb128fef6244305977342776bddf919Jaesung Chung    mPosition += size;
658409c0691fb128fef6244305977342776bddf919Jaesung Chung
668409c0691fb128fef6244305977342776bddf919Jaesung Chung    // Handle errors.
678409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (ferror(mFile) || (size == 0 && feof(mFile))) {
688409c0691fb128fef6244305977342776bddf919Jaesung Chung        ALOGV("GetData read failed: (offset: %zu, length: %zu)", offset, length);
698409c0691fb128fef6244305977342776bddf919Jaesung Chung        return piex::Error::kFail;
708409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
718409c0691fb128fef6244305977342776bddf919Jaesung Chung    return piex::Error::kOk;
728409c0691fb128fef6244305977342776bddf919Jaesung Chung}
738409c0691fb128fef6244305977342776bddf919Jaesung Chung
748409c0691fb128fef6244305977342776bddf919Jaesung Chungbool FileStream::exists() const {
758409c0691fb128fef6244305977342776bddf919Jaesung Chung    return mFile != NULL;
768409c0691fb128fef6244305977342776bddf919Jaesung Chung}
778409c0691fb128fef6244305977342776bddf919Jaesung Chung
788409c0691fb128fef6244305977342776bddf919Jaesung Chungsize_t FileStream::size() const {
798409c0691fb128fef6244305977342776bddf919Jaesung Chung    return mSize;
808409c0691fb128fef6244305977342776bddf919Jaesung Chung}
818409c0691fb128fef6244305977342776bddf919Jaesung Chung
828409c0691fb128fef6244305977342776bddf919Jaesung Chungbool GetExifFromRawImage(
83d4c505c9b4d5b0e743301e3f385895efdb9785d4Jaesung Chung        FileStream* stream, const String8& filename, piex::PreviewImageData& image_data) {
848f7a8f1eba590f4a0bb21988fc2a876dcb72dccdAnton Daubert    // Reset the PreviewImageData to its default.
858f7a8f1eba590f4a0bb21988fc2a876dcb72dccdAnton Daubert    image_data = piex::PreviewImageData();
868409c0691fb128fef6244305977342776bddf919Jaesung Chung
878409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (!stream->exists()) {
888409c0691fb128fef6244305977342776bddf919Jaesung Chung        // File is not exists.
898409c0691fb128fef6244305977342776bddf919Jaesung Chung        ALOGV("File is not exists: %s", filename.string());
908409c0691fb128fef6244305977342776bddf919Jaesung Chung        return false;
918409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
928409c0691fb128fef6244305977342776bddf919Jaesung Chung
938409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (!piex::IsRaw(stream)) {
948409c0691fb128fef6244305977342776bddf919Jaesung Chung        // Format not supported.
958409c0691fb128fef6244305977342776bddf919Jaesung Chung        ALOGV("Format not supported: %s", filename.string());
968409c0691fb128fef6244305977342776bddf919Jaesung Chung        return false;
978409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
988409c0691fb128fef6244305977342776bddf919Jaesung Chung
998409c0691fb128fef6244305977342776bddf919Jaesung Chung    piex::Error err = piex::GetPreviewImageData(stream, &image_data);
1008409c0691fb128fef6244305977342776bddf919Jaesung Chung
1018409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (err != piex::Error::kOk) {
1028409c0691fb128fef6244305977342776bddf919Jaesung Chung        // The input data seems to be broken.
1038409c0691fb128fef6244305977342776bddf919Jaesung Chung        ALOGV("Raw image not detected: %s (piex error code: %d)", filename.string(), (int32_t)err);
1048409c0691fb128fef6244305977342776bddf919Jaesung Chung        return false;
1058409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
1068409c0691fb128fef6244305977342776bddf919Jaesung Chung
1078409c0691fb128fef6244305977342776bddf919Jaesung Chung    if (image_data.thumbnail_offset + image_data.thumbnail_length > stream->size()) {
1088409c0691fb128fef6244305977342776bddf919Jaesung Chung        // Corrupted image.
1098409c0691fb128fef6244305977342776bddf919Jaesung Chung        ALOGV("Corrupted file: %s", filename.string());
1108409c0691fb128fef6244305977342776bddf919Jaesung Chung        return false;
1118409c0691fb128fef6244305977342776bddf919Jaesung Chung    }
1128409c0691fb128fef6244305977342776bddf919Jaesung Chung
1138409c0691fb128fef6244305977342776bddf919Jaesung Chung    return true;
1148409c0691fb128fef6244305977342776bddf919Jaesung Chung}
1158409c0691fb128fef6244305977342776bddf919Jaesung Chung
11679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dongbool ConvertKeyValueArraysToKeyedVector(
11779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        JNIEnv *env, jobjectArray keys, jobjectArray values,
11879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        KeyedVector<String8, String8>* keyedVector) {
11979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
12079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    int nKeyValuePairs = 0;
12179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    bool failed = false;
12279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    if (keys != NULL && values != NULL) {
12379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        nKeyValuePairs = env->GetArrayLength(keys);
12479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        failed = (nKeyValuePairs != env->GetArrayLength(values));
12579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
12679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
12779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    if (!failed) {
12879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        failed = ((keys != NULL && values == NULL) ||
12979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong                  (keys == NULL && values != NULL));
13079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
13179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
13279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    if (failed) {
1333762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("keys and values arrays have different length");
13479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
13579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        return false;
13679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
13779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
13879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    for (int i = 0; i < nKeyValuePairs; ++i) {
13979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        // No need to check on the ArrayIndexOutOfBoundsException, since
14079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        // it won't happen here.
14179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        jstring key = (jstring) env->GetObjectArrayElement(keys, i);
14279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        jstring value = (jstring) env->GetObjectArrayElement(values, i);
14379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
14479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        const char* keyStr = env->GetStringUTFChars(key, NULL);
14579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        if (!keyStr) {  // OutOfMemoryError
14679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong            return false;
14779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        }
14879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
14979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        const char* valueStr = env->GetStringUTFChars(value, NULL);
15079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        if (!valueStr) {  // OutOfMemoryError
15179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong            env->ReleaseStringUTFChars(key, keyStr);
15279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong            return false;
15379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        }
15479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
15579f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        keyedVector->add(String8(keyStr), String8(valueStr));
15679f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
15779f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->ReleaseStringUTFChars(key, keyStr);
15879f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->ReleaseStringUTFChars(value, valueStr);
15979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->DeleteLocalRef(key);
16079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong        env->DeleteLocalRef(value);
16179f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    }
16279f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong    return true;
16379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong}
16479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
16588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeIntegerObject(JNIEnv *env, int32_t value) {
1668d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Integer"));
1678d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
16888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1698d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID integerConstructID =
1708d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(I)V");
17188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(integerConstructID != NULL);
17288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1738d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    return env->NewObject(clazz.get(), integerConstructID, value);
17488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatic jobject makeLongObject(JNIEnv *env, int64_t value) {
1778d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Long"));
1788d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
17907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
1808d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID longConstructID = env->GetMethodID(clazz.get(), "<init>", "(J)V");
18107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    CHECK(longConstructID != NULL);
18207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
1838d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    return env->NewObject(clazz.get(), longConstructID, value);
18407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber}
18507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeFloatObject(JNIEnv *env, float value) {
1878d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Float"));
1888d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
18988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1908d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID floatConstructID =
1918d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(F)V");
19288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(floatConstructID != NULL);
19388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1948d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    return env->NewObject(clazz.get(), floatConstructID, value);
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeByteBufferObject(
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, const void *data, size_t size) {
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jbyteArray byteArrayObj = env->NewByteArray(size);
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->SetByteArrayRegion(byteArrayObj, 0, size, (const jbyte *)data);
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2028d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(env, env->FindClass("java/nio/ByteBuffer"));
2038d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
20488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID byteBufWrapID =
2068d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticMethodID(
2078d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                clazz.get(), "wrap", "([B)Ljava/nio/ByteBuffer;");
20888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(byteBufWrapID != NULL);
20988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject byteBufObj = env->CallStaticObjectMethod(
2118d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            clazz.get(), byteBufWrapID, byteArrayObj);
21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteLocalRef(byteArrayObj); byteArrayObj = NULL;
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return byteBufObj;
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
218b842599e51e2d3611503c3c7db1111358f99186dAndreas Huberstatic void SetMapInt32(
219b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber        JNIEnv *env, jobject hashMapObj, jmethodID hashMapPutID,
220b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber        const char *key, int32_t value) {
221b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    jstring keyObj = env->NewStringUTF(key);
222b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    jobject valueObj = makeIntegerObject(env, value);
223b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
2245a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe    env->CallObjectMethod(hashMapObj, hashMapPutID, keyObj, valueObj);
225b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
226b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    env->DeleteLocalRef(valueObj); valueObj = NULL;
227b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    env->DeleteLocalRef(keyObj); keyObj = NULL;
228b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber}
229b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t ConvertMessageToMap(
23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, const sp<AMessage> &msg, jobject *map) {
2328d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> hashMapClazz(
2338d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("java/util/HashMap"));
23488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2358d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    if (hashMapClazz.get() == NULL) {
23688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
23788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
23888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID hashMapConstructID =
2408d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(hashMapClazz.get(), "<init>", "()V");
24188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapConstructID == NULL) {
24388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
24488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID hashMapPutID =
24788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->GetMethodID(
2488d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                hashMapClazz.get(),
24988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "put",
25088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
25188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapPutID == NULL) {
25388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
25488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2568d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jobject hashMap = env->NewObject(hashMapClazz.get(), hashMapConstructID);
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < msg->countEntries(); ++i) {
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        AMessage::Type valueType;
26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *key = msg->getEntryNameAt(i, &valueType);
26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject valueObj = NULL;
26388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        switch (valueType) {
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeInt32:
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                int32_t val;
26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findInt32(key, &val));
26988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeIntegerObject(env, val);
27107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                break;
27207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber            }
27307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
27407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber            case AMessage::kTypeInt64:
27507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber            {
27607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                int64_t val;
27707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                CHECK(msg->findInt64(key, &val));
27807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
27907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                valueObj = makeLongObject(env, val);
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeFloat:
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                float val;
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findFloat(key, &val));
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeFloatObject(env, val);
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeString:
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                AString val;
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findString(key, &val));
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = env->NewStringUTF(val.c_str());
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3015c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber            case AMessage::kTypeBuffer:
30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
3035c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber                sp<ABuffer> buffer;
3045c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber                CHECK(msg->findBuffer(key, &buffer));
30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeByteBufferObject(
30788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        env, buffer->data(), buffer->size());
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
311b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            case AMessage::kTypeRect:
312b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            {
313b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                int32_t left, top, right, bottom;
314b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                CHECK(msg->findRect(key, &left, &top, &right, &bottom));
315b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
316b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
317b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
318b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
319b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
320f953ca2ec8e418d54ab7d4585302db22964bcb70Elliott Hughes                        AStringPrintf("%s-left", key).c_str(),
321b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        left);
322b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
323b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
324b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
325b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
326b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
327f953ca2ec8e418d54ab7d4585302db22964bcb70Elliott Hughes                        AStringPrintf("%s-top", key).c_str(),
328b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        top);
329b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
330b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
331b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
332b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
333b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
334f953ca2ec8e418d54ab7d4585302db22964bcb70Elliott Hughes                        AStringPrintf("%s-right", key).c_str(),
335b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        right);
336b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
337b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
338b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
339b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
340b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
341f953ca2ec8e418d54ab7d4585302db22964bcb70Elliott Hughes                        AStringPrintf("%s-bottom", key).c_str(),
342b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        bottom);
343b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                break;
344b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            }
345b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            default:
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (valueObj != NULL) {
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jstring keyObj = env->NewStringUTF(key);
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3535a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe            env->CallObjectMethod(hashMap, hashMapPutID, keyObj, valueObj);
35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->DeleteLocalRef(keyObj); keyObj = NULL;
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->DeleteLocalRef(valueObj); valueObj = NULL;
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
35988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *map = hashMap;
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t ConvertKeyValueArraysToMessage(
36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobjectArray keys, jobjectArray values,
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        sp<AMessage> *out) {
3688d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> stringClass(env, env->FindClass("java/lang/String"));
3698d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(stringClass.get() != NULL);
3708d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> integerClass(env, env->FindClass("java/lang/Integer"));
3718d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(integerClass.get() != NULL);
3728d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> longClass(env, env->FindClass("java/lang/Long"));
3738d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(longClass.get() != NULL);
3748d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> floatClass(env, env->FindClass("java/lang/Float"));
3758d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(floatClass.get() != NULL);
3768d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
3778d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(byteBufClass.get() != NULL);
37888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg = new AMessage;
38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jsize numEntries = 0;
38288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (keys != NULL) {
38488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (values == NULL) {
38588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        numEntries = env->GetArrayLength(keys);
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (numEntries != env->GetArrayLength(values)) {
39188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (values != NULL) {
39488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (jsize i = 0; i < numEntries; ++i) {
39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject keyObj = env->GetObjectArrayElement(keys, i);
39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4008d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        if (!env->IsInstanceOf(keyObj, stringClass.get())) {
40188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *tmp = env->GetStringUTFChars((jstring)keyObj, NULL);
40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (tmp == NULL) {
40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -ENOMEM;
40888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
40988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        AString key = tmp;
41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->ReleaseStringUTFChars((jstring)keyObj, tmp);
41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        tmp = NULL;
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject valueObj = env->GetObjectArrayElement(values, i);
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4178d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        if (env->IsInstanceOf(valueObj, stringClass.get())) {
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            const char *value = env->GetStringUTFChars((jstring)valueObj, NULL);
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            if (value == NULL) {
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                return -ENOMEM;
42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setString(key.c_str(), value);
42588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->ReleaseStringUTFChars((jstring)valueObj, value);
42788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            value = NULL;
4288d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        } else if (env->IsInstanceOf(valueObj, integerClass.get())) {
42988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID intValueID =
4308d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(integerClass.get(), "intValue", "()I");
43188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(intValueID != NULL);
43288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint value = env->CallIntMethod(valueObj, intValueID);
43488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setInt32(key.c_str(), value);
4368d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        } else if (env->IsInstanceOf(valueObj, longClass.get())) {
4378d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            jmethodID longValueID =
4388d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(longClass.get(), "longValue", "()J");
4398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            CHECK(longValueID != NULL);
4408d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
4418d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            jlong value = env->CallLongMethod(valueObj, longValueID);
4428d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
4438d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            msg->setInt64(key.c_str(), value);
4448d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        } else if (env->IsInstanceOf(valueObj, floatClass.get())) {
44588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID floatValueID =
4468d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(floatClass.get(), "floatValue", "()F");
44788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(floatValueID != NULL);
44888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jfloat value = env->CallFloatMethod(valueObj, floatValueID);
45088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setFloat(key.c_str(), value);
4528d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        } else if (env->IsInstanceOf(valueObj, byteBufClass.get())) {
45388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID positionID =
4548d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(byteBufClass.get(), "position", "()I");
45588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(positionID != NULL);
45688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID limitID =
4588d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                env->GetMethodID(byteBufClass.get(), "limit", "()I");
45988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(limitID != NULL);
46088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint position = env->CallIntMethod(valueObj, positionID);
46288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint limit = env->CallIntMethod(valueObj, limitID);
46388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            sp<ABuffer> buffer = new ABuffer(limit - position);
46588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            void *data = env->GetDirectBufferAddress(valueObj);
46788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            if (data != NULL) {
46988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                memcpy(buffer->data(),
47088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                       (const uint8_t *)data + position,
47188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                       buffer->size());
47288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            } else {
47388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                jmethodID arrayID =
4748d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber                    env->GetMethodID(byteBufClass.get(), "array", "()[B");
47588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(arrayID != NULL);
47688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
47788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                jbyteArray byteArray =
47888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    (jbyteArray)env->CallObjectMethod(valueObj, arrayID);
47988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(byteArray != NULL);
48088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetByteArrayRegion(
48288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        byteArray,
48388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        position,
48488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        buffer->size(),
48588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        (jbyte *)buffer->data());
48688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->DeleteLocalRef(byteArray); byteArray = NULL;
48888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
48988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4909b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber            msg->setBuffer(key.c_str(), buffer);
49188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
49288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
49388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *out = msg;
49588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
49788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
49888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49979f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong}  // namespace android
50079f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
501