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
8807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huberstatic jobject makeLongObject(JNIEnv *env, int64_t value) {
8907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    jclass clazz = env->FindClass("java/lang/Long");
9007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    CHECK(clazz != NULL);
9107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
9207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    jmethodID longConstructID = env->GetMethodID(clazz, "<init>", "(J)V");
9307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    CHECK(longConstructID != NULL);
9407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
9507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber    return env->NewObject(clazz, longConstructID, value);
9607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber}
9707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeFloatObject(JNIEnv *env, float value) {
9988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("java/lang/Float");
10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID floatConstructID = env->GetMethodID(clazz, "<init>", "(F)V");
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(floatConstructID != NULL);
10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return env->NewObject(clazz, floatConstructID, value);
10688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
10788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject makeByteBufferObject(
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, const void *data, size_t size) {
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jbyteArray byteArrayObj = env->NewByteArray(size);
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->SetByteArrayRegion(byteArrayObj, 0, size, (const jbyte *)data);
11288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("java/nio/ByteBuffer");
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID byteBufWrapID =
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->GetStaticMethodID(clazz, "wrap", "([B)Ljava/nio/ByteBuffer;");
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(byteBufWrapID != NULL);
11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject byteBufObj = env->CallStaticObjectMethod(
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            clazz, byteBufWrapID, byteArrayObj);
12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteLocalRef(byteArrayObj); byteArrayObj = NULL;
12488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return byteBufObj;
12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
12788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
128b842599e51e2d3611503c3c7db1111358f99186dAndreas Huberstatic void SetMapInt32(
129b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber        JNIEnv *env, jobject hashMapObj, jmethodID hashMapPutID,
130b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber        const char *key, int32_t value) {
131b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    jstring keyObj = env->NewStringUTF(key);
132b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    jobject valueObj = makeIntegerObject(env, value);
133b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
134b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    jobject res = env->CallObjectMethod(
135b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            hashMapObj, hashMapPutID, keyObj, valueObj);
136b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
137b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    env->DeleteLocalRef(valueObj); valueObj = NULL;
138b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber    env->DeleteLocalRef(keyObj); keyObj = NULL;
139b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber}
140b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
14188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t ConvertMessageToMap(
14288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, const sp<AMessage> &msg, jobject *map) {
14388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass hashMapClazz = env->FindClass("java/util/HashMap");
14488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapClazz == NULL) {
14688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
14788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
14888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID hashMapConstructID =
15088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->GetMethodID(hashMapClazz, "<init>", "()V");
15188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapConstructID == NULL) {
15388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
15488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
15588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID hashMapPutID =
15788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->GetMethodID(
15888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                hashMapClazz,
15988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "put",
16088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
16188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (hashMapPutID == NULL) {
16388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
16488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
16588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject hashMap = env->NewObject(hashMapClazz, hashMapConstructID);
16788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < msg->countEntries(); ++i) {
16988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        AMessage::Type valueType;
17088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *key = msg->getEntryNameAt(i, &valueType);
17188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject valueObj = NULL;
17388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        switch (valueType) {
17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeInt32:
17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                int32_t val;
17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findInt32(key, &val));
17988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeIntegerObject(env, val);
18107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                break;
18207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber            }
18307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
18407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber            case AMessage::kTypeInt64:
18507ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber            {
18607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                int64_t val;
18707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                CHECK(msg->findInt64(key, &val));
18807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber
18907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber                valueObj = makeLongObject(env, val);
19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
19188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
19288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeFloat:
19488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                float val;
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findFloat(key, &val));
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeFloatObject(env, val);
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            case AMessage::kTypeString:
20388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
20488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                AString val;
20588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(msg->findString(key, &val));
20688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = env->NewStringUTF(val.c_str());
20888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
20988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2115c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber            case AMessage::kTypeBuffer:
21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            {
2135c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber                sp<ABuffer> buffer;
2145c850396b39a57baabd37a9c0c8324f1bee408caAndreas Huber                CHECK(msg->findBuffer(key, &buffer));
21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                valueObj = makeByteBufferObject(
21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        env, buffer->data(), buffer->size());
21888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
22088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
221b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            case AMessage::kTypeRect:
222b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            {
223b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                int32_t left, top, right, bottom;
224b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                CHECK(msg->findRect(key, &left, &top, &right, &bottom));
225b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
226b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
227b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
228b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
229b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
230b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        StringPrintf("%s-left", key).c_str(),
231b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        left);
232b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
233b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
234b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
235b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
236b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
237b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        StringPrintf("%s-top", key).c_str(),
238b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        top);
239b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
240b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
241b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
242b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
243b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
244b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        StringPrintf("%s-right", key).c_str(),
245b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        right);
246b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
247b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                SetMapInt32(
248b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        env,
249b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMap,
250b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        hashMapPutID,
251b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        StringPrintf("%s-bottom", key).c_str(),
252b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                        bottom);
253b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber                break;
254b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber            }
255b842599e51e2d3611503c3c7db1111358f99186dAndreas Huber
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            default:
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                break;
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (valueObj != NULL) {
26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jstring keyObj = env->NewStringUTF(key);
26288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jobject res = env->CallObjectMethod(
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    hashMap, hashMapPutID, keyObj, valueObj);
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->DeleteLocalRef(keyObj); keyObj = NULL;
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->DeleteLocalRef(valueObj); valueObj = NULL;
26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
26988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
27088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *map = hashMap;
27288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
27488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
27588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t ConvertKeyValueArraysToMessage(
27788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobjectArray keys, jobjectArray values,
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        sp<AMessage> *out) {
27988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass stringClass = env->FindClass("java/lang/String");
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(stringClass != NULL);
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass integerClass = env->FindClass("java/lang/Integer");
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(integerClass != NULL);
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass floatClass = env->FindClass("java/lang/Float");
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(floatClass != NULL);
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass byteBufClass = env->FindClass("java/nio/ByteBuffer");
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(byteBufClass != NULL);
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg = new AMessage;
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jsize numEntries = 0;
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (keys != NULL) {
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (values == NULL) {
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        numEntries = env->GetArrayLength(keys);
30188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (numEntries != env->GetArrayLength(values)) {
30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
30488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else if (values != NULL) {
30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -EINVAL;
30788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (jsize i = 0; i < numEntries; ++i) {
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject keyObj = env->GetObjectArrayElement(keys, i);
31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (!env->IsInstanceOf(keyObj, stringClass)) {
31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -EINVAL;
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *tmp = env->GetStringUTFChars((jstring)keyObj, NULL);
31788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (tmp == NULL) {
31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return -ENOMEM;
32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        AString key = tmp;
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->ReleaseStringUTFChars((jstring)keyObj, tmp);
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        tmp = NULL;
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject valueObj = env->GetObjectArrayElement(values, i);
32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (env->IsInstanceOf(valueObj, stringClass)) {
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            const char *value = env->GetStringUTFChars((jstring)valueObj, NULL);
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            if (value == NULL) {
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                return -ENOMEM;
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setString(key.c_str(), value);
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->ReleaseStringUTFChars((jstring)valueObj, value);
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            value = NULL;
34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else if (env->IsInstanceOf(valueObj, integerClass)) {
34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID intValueID =
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetMethodID(integerClass, "intValue", "()I");
34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(intValueID != NULL);
34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint value = env->CallIntMethod(valueObj, intValueID);
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setInt32(key.c_str(), value);
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else if (env->IsInstanceOf(valueObj, floatClass)) {
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID floatValueID =
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetMethodID(floatClass, "floatValue", "()F");
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(floatValueID != NULL);
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jfloat value = env->CallFloatMethod(valueObj, floatValueID);
35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            msg->setFloat(key.c_str(), value);
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else if (env->IsInstanceOf(valueObj, byteBufClass)) {
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID positionID =
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetMethodID(byteBufClass, "position", "()I");
35988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(positionID != NULL);
36088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jmethodID limitID =
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetMethodID(byteBufClass, "limit", "()I");
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            CHECK(limitID != NULL);
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint position = env->CallIntMethod(valueObj, positionID);
36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jint limit = env->CallIntMethod(valueObj, limitID);
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            sp<ABuffer> buffer = new ABuffer(limit - position);
36988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            void *data = env->GetDirectBufferAddress(valueObj);
37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            if (data != NULL) {
37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                memcpy(buffer->data(),
37488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                       (const uint8_t *)data + position,
37588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                       buffer->size());
37688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            } else {
37788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                jmethodID arrayID =
37888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env->GetMethodID(byteBufClass, "array", "()[B");
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(arrayID != NULL);
38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                jbyteArray byteArray =
38288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    (jbyteArray)env->CallObjectMethod(valueObj, arrayID);
38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                CHECK(byteArray != NULL);
38488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->GetByteArrayRegion(
38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        byteArray,
38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        position,
38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        buffer->size(),
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                        (jbyte *)buffer->data());
39088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env->DeleteLocalRef(byteArray); byteArray = NULL;
39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            }
39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3949b8e496f4d143280deff137c5f30ca8907bc28dbAndreas Huber            msg->setBuffer(key.c_str(), buffer);
39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
39788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *out = msg;
39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
40188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40379f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong}  // namespace android
40479f407cc6c5ae34fc6f04d52fd034b49d1f002c4James Dong
405