Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2018, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef _ANDROID_MEDIA_AUDIO_PRESENTATION_H_
     18 #define _ANDROID_MEDIA_AUDIO_PRESENTATION_H_
     19 
     20 #include "jni.h"
     21 
     22 #include <media/AudioPresentationInfo.h>
     23 #include <media/stagefright/foundation/ADebug.h>
     24 #include <media/stagefright/foundation/AMessage.h>
     25 
     26 #include <nativehelper/ScopedLocalRef.h>
     27 
     28 namespace android {
     29 
     30 struct JAudioPresentationInfo {
     31     struct fields_t {
     32         jclass      clazz;
     33         jmethodID   constructID;
     34 
     35         // list parameters
     36         jclass listclazz;
     37         jmethodID listConstructId;
     38         jmethodID listAddId;
     39 
     40         void init(JNIEnv *env) {
     41             jclass lclazz = env->FindClass("android/media/AudioPresentation");
     42             if (lclazz == NULL) {
     43                 return;
     44             }
     45 
     46             clazz = (jclass)env->NewGlobalRef(lclazz);
     47             if (clazz == NULL) {
     48                 return;
     49             }
     50 
     51             constructID = env->GetMethodID(clazz, "<init>",
     52                                 "(IILjava/util/Map;Ljava/lang/String;IZZZ)V");
     53             env->DeleteLocalRef(lclazz);
     54 
     55             // list objects
     56             jclass llistclazz = env->FindClass("java/util/ArrayList");
     57             CHECK(llistclazz != NULL);
     58             listclazz = static_cast<jclass>(env->NewGlobalRef(llistclazz));
     59             CHECK(listclazz != NULL);
     60             listConstructId = env->GetMethodID(listclazz, "<init>", "()V");
     61             CHECK(listConstructId != NULL);
     62             listAddId = env->GetMethodID(listclazz, "add", "(Ljava/lang/Object;)Z");
     63             CHECK(listAddId != NULL);
     64             env->DeleteLocalRef(llistclazz);
     65         }
     66 
     67         void exit(JNIEnv *env) {
     68             env->DeleteGlobalRef(clazz);
     69             clazz = NULL;
     70             env->DeleteGlobalRef(listclazz);
     71             listclazz = NULL;
     72         }
     73     };
     74 
     75     static status_t ConvertMessageToMap(JNIEnv *env, const sp<AMessage> &msg, jobject *map) {
     76         ScopedLocalRef<jclass> hashMapClazz(env, env->FindClass("java/util/HashMap"));
     77 
     78         if (hashMapClazz.get() == NULL) {
     79             return -EINVAL;
     80         }
     81         jmethodID hashMapConstructID =
     82             env->GetMethodID(hashMapClazz.get(), "<init>", "()V");
     83 
     84         if (hashMapConstructID == NULL) {
     85             return -EINVAL;
     86         }
     87         jmethodID hashMapPutID =
     88             env->GetMethodID(
     89                     hashMapClazz.get(),
     90                     "put",
     91                     "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
     92 
     93         if (hashMapPutID == NULL) {
     94             return -EINVAL;
     95         }
     96 
     97         jobject hashMap = env->NewObject(hashMapClazz.get(), hashMapConstructID);
     98 
     99         for (size_t i = 0; i < msg->countEntries(); ++i) {
    100             AMessage::Type valueType;
    101             const char *key = msg->getEntryNameAt(i, &valueType);
    102 
    103             if (!strncmp(key, "android._", 9)) {
    104                 // don't expose private keys (starting with android._)
    105                 continue;
    106             }
    107 
    108             jobject valueObj = NULL;
    109 
    110             AString val;
    111             CHECK(msg->findString(key, &val));
    112 
    113             valueObj = env->NewStringUTF(val.c_str());
    114 
    115             if (valueObj != NULL) {
    116                 jstring keyObj = env->NewStringUTF(key);
    117 
    118                 env->CallObjectMethod(hashMap, hashMapPutID, keyObj, valueObj);
    119 
    120                 env->DeleteLocalRef(keyObj); keyObj = NULL;
    121                 env->DeleteLocalRef(valueObj); valueObj = NULL;
    122             }
    123         }
    124 
    125         *map = hashMap;
    126 
    127         return OK;
    128     }
    129 
    130     jobject asJobject(JNIEnv *env, const fields_t& fields, const AudioPresentationInfo &info) {
    131         jobject list = env->NewObject(fields.listclazz, fields.listConstructId);
    132 
    133         for (size_t i = 0; i < info.countPresentations(); ++i) {
    134             const sp<AudioPresentation> &ap = info.getPresentation(i);
    135             jobject jLabelObject;
    136 
    137             sp<AMessage> labelMessage = new AMessage();
    138             for (size_t i = 0; i < ap->mLabels.size(); ++i) {
    139                 labelMessage->setString(ap->mLabels.keyAt(i).string(),
    140                                         ap->mLabels.valueAt(i).string());
    141             }
    142             if (ConvertMessageToMap(env, labelMessage, &jLabelObject) != OK) {
    143                 return NULL;
    144             }
    145             jstring jLanguage = env->NewStringUTF(ap->mLanguage.string());
    146 
    147             jobject jValueObj = env->NewObject(fields.clazz, fields.constructID,
    148                                 static_cast<jint>(ap->mPresentationId),
    149                                 static_cast<jint>(ap->mProgramId),
    150                                 jLabelObject,
    151                                 jLanguage,
    152                                 static_cast<jint>(ap->mMasteringIndication),
    153                                 static_cast<jboolean>((ap->mAudioDescriptionAvailable == 1) ?
    154                                     1 : 0),
    155                                 static_cast<jboolean>((ap->mSpokenSubtitlesAvailable == 1) ?
    156                                     1 : 0),
    157                                 static_cast<jboolean>((ap->mDialogueEnhancementAvailable == 1) ?
    158                                     1 : 0));
    159             if (jValueObj == NULL) {
    160                 env->DeleteLocalRef(jLanguage); jLanguage = NULL;
    161                 return NULL;
    162             }
    163 
    164             env->CallBooleanMethod(list, fields.listAddId, jValueObj);
    165             env->DeleteLocalRef(jValueObj); jValueObj = NULL;
    166             env->DeleteLocalRef(jLanguage); jLanguage = NULL;
    167         }
    168         return list;
    169     }
    170 };
    171 }  // namespace android
    172 
    173 #endif  // _ANDROID_MEDIA_AUDIO_PRESENTATION_H_
    174