158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo/*
258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo * Copyright 2018, The Android Open Source Project
358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo *
458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo * Licensed under the Apache License, Version 2.0 (the "License");
558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo * you may not use this file except in compliance with the License.
658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo * You may obtain a copy of the License at
758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo *
858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo *     http://www.apache.org/licenses/LICENSE-2.0
958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo *
1058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo * Unless required by applicable law or agreed to in writing, software
1158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo * distributed under the License is distributed on an "AS IS" BASIS,
1258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo * See the License for the specific language governing permissions and
1458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo * limitations under the License.
1558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo */
1658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
1758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo#ifndef _ANDROID_MEDIA_AUDIO_PRESENTATION_H_
1858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo#define _ANDROID_MEDIA_AUDIO_PRESENTATION_H_
1958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
2058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo#include "jni.h"
2158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
2258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo#include <media/AudioPresentationInfo.h>
2358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo#include <media/stagefright/foundation/ADebug.h>
2458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo#include <media/stagefright/foundation/AMessage.h>
2558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
2658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo#include <nativehelper/ScopedLocalRef.h>
2758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
2858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroonamespace android {
2958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
3058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroostruct JAudioPresentationInfo {
3158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo    struct fields_t {
3258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        jclass      clazz;
3358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        jmethodID   constructID;
3458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
3558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        // list parameters
3658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        jclass listclazz;
3758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        jmethodID listConstructId;
3858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        jmethodID listAddId;
3958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
4058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        void init(JNIEnv *env) {
4158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            jclass lclazz = env->FindClass("android/media/AudioPresentation");
4258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            if (lclazz == NULL) {
4358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                return;
4458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            }
4558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
4658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            clazz = (jclass)env->NewGlobalRef(lclazz);
4758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            if (clazz == NULL) {
4858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                return;
4958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            }
5058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
5158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            constructID = env->GetMethodID(clazz, "<init>",
5258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                "(IILjava/util/Map;Ljava/lang/String;IZZZ)V");
5358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            env->DeleteLocalRef(lclazz);
5458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
5558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            // list objects
5658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            jclass llistclazz = env->FindClass("java/util/ArrayList");
5758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            CHECK(llistclazz != NULL);
5858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            listclazz = static_cast<jclass>(env->NewGlobalRef(llistclazz));
5958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            CHECK(listclazz != NULL);
6058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            listConstructId = env->GetMethodID(listclazz, "<init>", "()V");
6158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            CHECK(listConstructId != NULL);
6258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            listAddId = env->GetMethodID(listclazz, "add", "(Ljava/lang/Object;)Z");
6358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            CHECK(listAddId != NULL);
6458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            env->DeleteLocalRef(llistclazz);
6558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        }
6658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
6758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        void exit(JNIEnv *env) {
6858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            env->DeleteGlobalRef(clazz);
6958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            clazz = NULL;
7058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            env->DeleteGlobalRef(listclazz);
7158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            listclazz = NULL;
7258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        }
7358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo    };
7458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
7558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo    static status_t ConvertMessageToMap(JNIEnv *env, const sp<AMessage> &msg, jobject *map) {
7658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        ScopedLocalRef<jclass> hashMapClazz(env, env->FindClass("java/util/HashMap"));
7758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
7858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        if (hashMapClazz.get() == NULL) {
7958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            return -EINVAL;
8058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        }
8158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        jmethodID hashMapConstructID =
8258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            env->GetMethodID(hashMapClazz.get(), "<init>", "()V");
8358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
8458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        if (hashMapConstructID == NULL) {
8558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            return -EINVAL;
8658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        }
8758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        jmethodID hashMapPutID =
8858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            env->GetMethodID(
8958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                    hashMapClazz.get(),
9058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                    "put",
9158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                    "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
9258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
9358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        if (hashMapPutID == NULL) {
9458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            return -EINVAL;
9558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        }
9658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
9758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        jobject hashMap = env->NewObject(hashMapClazz.get(), hashMapConstructID);
9858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
9958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        for (size_t i = 0; i < msg->countEntries(); ++i) {
10058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            AMessage::Type valueType;
10158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            const char *key = msg->getEntryNameAt(i, &valueType);
10258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
10358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            if (!strncmp(key, "android._", 9)) {
10458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                // don't expose private keys (starting with android._)
10558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                continue;
10658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            }
10758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
10858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            jobject valueObj = NULL;
10958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
11058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            AString val;
11158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            CHECK(msg->findString(key, &val));
11258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
11358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            valueObj = env->NewStringUTF(val.c_str());
11458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
11558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            if (valueObj != NULL) {
11658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                jstring keyObj = env->NewStringUTF(key);
11758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
11858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                env->CallObjectMethod(hashMap, hashMapPutID, keyObj, valueObj);
11958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
12058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                env->DeleteLocalRef(keyObj); keyObj = NULL;
12158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                env->DeleteLocalRef(valueObj); valueObj = NULL;
12258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            }
12358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        }
12458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
12558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        *map = hashMap;
12658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
12758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        return OK;
12858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo    }
12958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
13058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo    jobject asJobject(JNIEnv *env, const fields_t& fields, const AudioPresentationInfo &info) {
13158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        jobject list = env->NewObject(fields.listclazz, fields.listConstructId);
13258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
13358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        for (size_t i = 0; i < info.countPresentations(); ++i) {
13458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            const sp<AudioPresentation> &ap = info.getPresentation(i);
13558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            jobject jLabelObject;
13658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
13758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            sp<AMessage> labelMessage = new AMessage();
13858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            for (size_t i = 0; i < ap->mLabels.size(); ++i) {
13958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                labelMessage->setString(ap->mLabels.keyAt(i).string(),
14058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                        ap->mLabels.valueAt(i).string());
14158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            }
14258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            if (ConvertMessageToMap(env, labelMessage, &jLabelObject) != OK) {
14358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                return NULL;
14458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            }
14558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            jstring jLanguage = env->NewStringUTF(ap->mLanguage.string());
14658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
14758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            jobject jValueObj = env->NewObject(fields.clazz, fields.constructID,
14858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                static_cast<jint>(ap->mPresentationId),
14958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                static_cast<jint>(ap->mProgramId),
15058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                jLabelObject,
15158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                jLanguage,
15258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                static_cast<jint>(ap->mMasteringIndication),
15358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                static_cast<jboolean>((ap->mAudioDescriptionAvailable == 1) ?
15458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                    1 : 0),
15558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                static_cast<jboolean>((ap->mSpokenSubtitlesAvailable == 1) ?
15658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                    1 : 0),
15758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                static_cast<jboolean>((ap->mDialogueEnhancementAvailable == 1) ?
15858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                                    1 : 0));
15958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            if (jValueObj == NULL) {
16058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                env->DeleteLocalRef(jLanguage); jLanguage = NULL;
16158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo                return NULL;
16258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            }
16358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
16458822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            env->CallBooleanMethod(list, fields.listAddId, jValueObj);
16558822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            env->DeleteLocalRef(jValueObj); jValueObj = NULL;
16658822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo            env->DeleteLocalRef(jLanguage); jLanguage = NULL;
16758822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        }
16858822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo        return list;
16958822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo    }
17058822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo};
17158822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo}  // namespace android
17258822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo
17358822bec4eb6e0930f2efc0da5b6e464b193c558Previr Rangroo#endif  // _ANDROID_MEDIA_AUDIO_PRESENTATION_H_
174