Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2017, 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 #define LOG_TAG "MediaMetricsJNI"
     18 
     19 #include <jni.h>
     20 #include <nativehelper/JNIHelp.h>
     21 
     22 #include "android_media_MediaMetricsJNI.h"
     23 #include <media/MediaAnalyticsItem.h>
     24 
     25 
     26 // This source file is compiled and linked into both:
     27 // core/jni/ (libandroid_runtime.so)
     28 // media/jni (libmedia2_jni.so)
     29 
     30 namespace android {
     31 
     32 // place the attributes into a java PersistableBundle object
     33 jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
     34 
     35     jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
     36     if (clazzBundle==NULL) {
     37         ALOGE("can't find android/os/PersistableBundle");
     38         return NULL;
     39     }
     40     // sometimes the caller provides one for us to fill
     41     if (mybundle == NULL) {
     42         // create the bundle
     43         jmethodID constructID = env->GetMethodID(clazzBundle, "<init>", "()V");
     44         mybundle = env->NewObject(clazzBundle, constructID);
     45         if (mybundle == NULL) {
     46             return NULL;
     47         }
     48     }
     49 
     50     // grab methods that we can invoke
     51     jmethodID setIntID = env->GetMethodID(clazzBundle, "putInt", "(Ljava/lang/String;I)V");
     52     jmethodID setLongID = env->GetMethodID(clazzBundle, "putLong", "(Ljava/lang/String;J)V");
     53     jmethodID setDoubleID = env->GetMethodID(clazzBundle, "putDouble", "(Ljava/lang/String;D)V");
     54     jmethodID setStringID = env->GetMethodID(clazzBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V");
     55 
     56     // env, class, method, {parms}
     57     //env->CallVoidMethod(env, mybundle, setIntID, jstr, jint);
     58 
     59     // iterate through my attributes
     60     // -- get name, get type, get value
     61     // -- insert appropriately into the bundle
     62     for (size_t i = 0 ; i < item->mPropCount; i++ ) {
     63             MediaAnalyticsItem::Prop *prop = &item->mProps[i];
     64             // build the key parameter from prop->mName
     65             jstring keyName = env->NewStringUTF(prop->mName);
     66             // invoke the appropriate method to insert
     67             switch (prop->mType) {
     68                 case MediaAnalyticsItem::kTypeInt32:
     69                     env->CallVoidMethod(mybundle, setIntID,
     70                                         keyName, (jint) prop->u.int32Value);
     71                     break;
     72                 case MediaAnalyticsItem::kTypeInt64:
     73                     env->CallVoidMethod(mybundle, setLongID,
     74                                         keyName, (jlong) prop->u.int64Value);
     75                     break;
     76                 case MediaAnalyticsItem::kTypeDouble:
     77                     env->CallVoidMethod(mybundle, setDoubleID,
     78                                         keyName, (jdouble) prop->u.doubleValue);
     79                     break;
     80                 case MediaAnalyticsItem::kTypeCString:
     81                     env->CallVoidMethod(mybundle, setStringID, keyName,
     82                                         env->NewStringUTF(prop->u.CStringValue));
     83                     break;
     84                 default:
     85                         ALOGE("to_String bad item type: %d for %s",
     86                               prop->mType, prop->mName);
     87                         break;
     88             }
     89     }
     90 
     91     return mybundle;
     92 }
     93 
     94 // convert the specified batch  metrics attributes to a persistent bundle.
     95 // The encoding of the byte array is specified in
     96 //     frameworks/av/media/libmediametrics/MediaAnalyticsItem.cpp
     97 //
     98 // type encodings; matches frameworks/av/media/libmediametrics/MediaAnalyticsItem.cpp
     99 enum { kInt32 = 0, kInt64, kDouble, kRate, kCString};
    100 
    101 jobject MediaMetricsJNI::writeAttributesToBundle(JNIEnv* env, jobject mybundle, char *buffer, size_t length) {
    102     ALOGV("writeAttributes()");
    103 
    104     if (buffer == NULL || length <= 0) {
    105         ALOGW("bad parameters to writeAttributesToBundle()");
    106         return NULL;
    107     }
    108 
    109     jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
    110     if (clazzBundle==NULL) {
    111         ALOGE("can't find android/os/PersistableBundle");
    112         return NULL;
    113     }
    114     // sometimes the caller provides one for us to fill
    115     if (mybundle == NULL) {
    116         // create the bundle
    117         jmethodID constructID = env->GetMethodID(clazzBundle, "<init>", "()V");
    118         mybundle = env->NewObject(clazzBundle, constructID);
    119         if (mybundle == NULL) {
    120             ALOGD("unable to create mybundle");
    121             return NULL;
    122         }
    123     }
    124 
    125     int left = length;
    126     char *buf = buffer;
    127 
    128     // grab methods that we can invoke
    129     jmethodID setIntID = env->GetMethodID(clazzBundle, "putInt", "(Ljava/lang/String;I)V");
    130     jmethodID setLongID = env->GetMethodID(clazzBundle, "putLong", "(Ljava/lang/String;J)V");
    131     jmethodID setDoubleID = env->GetMethodID(clazzBundle, "putDouble", "(Ljava/lang/String;D)V");
    132     jmethodID setStringID = env->GetMethodID(clazzBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V");
    133 
    134 
    135 #define _EXTRACT(size, val) \
    136     { if ((size) > left) goto badness; memcpy(&val, buf, (size)); buf += (size); left -= (size);}
    137 #define _SKIP(size) \
    138     { if ((size) > left) goto badness; buf += (size); left -= (size);}
    139 
    140     int32_t bufsize;
    141     _EXTRACT(sizeof(int32_t), bufsize);
    142     if (bufsize != length) {
    143         goto badness;
    144     }
    145     int32_t proto;
    146     _EXTRACT(sizeof(int32_t), proto);
    147     if (proto != 0) {
    148         ALOGE("unsupported wire protocol %d", proto);
    149         goto badness;
    150     }
    151 
    152     int32_t count;
    153     _EXTRACT(sizeof(int32_t), count);
    154 
    155     // iterate through my attributes
    156     // -- get name, get type, get value, insert into bundle appropriately.
    157     for (int i = 0 ; i < count; i++ ) {
    158             // prop name len (int16)
    159             int16_t keylen;
    160             _EXTRACT(sizeof(int16_t), keylen);
    161             if (keylen <= 0) goto badness;
    162             // prop name itself
    163             char *key = buf;
    164             jstring keyName = env->NewStringUTF(buf);
    165             _SKIP(keylen);
    166 
    167             // prop type (int8_t)
    168             int8_t attrType;
    169             _EXTRACT(sizeof(int8_t), attrType);
    170 
    171 	    int16_t attrSize;
    172             _EXTRACT(sizeof(int16_t), attrSize);
    173 
    174             switch (attrType) {
    175                 case kInt32:
    176                     {
    177                         int32_t i32;
    178                         _EXTRACT(sizeof(int32_t), i32);
    179                         env->CallVoidMethod(mybundle, setIntID,
    180                                             keyName, (jint) i32);
    181                         break;
    182                     }
    183                 case kInt64:
    184                     {
    185                         int64_t i64;
    186                         _EXTRACT(sizeof(int64_t), i64);
    187                         env->CallVoidMethod(mybundle, setLongID,
    188                                             keyName, (jlong) i64);
    189                         break;
    190                     }
    191                 case kDouble:
    192                     {
    193                         double d64;
    194                         _EXTRACT(sizeof(double), d64);
    195                         env->CallVoidMethod(mybundle, setDoubleID,
    196                                             keyName, (jdouble) d64);
    197                         break;
    198                     }
    199                 case kCString:
    200                     {
    201                         jstring value = env->NewStringUTF(buf);
    202                         env->CallVoidMethod(mybundle, setStringID,
    203                                             keyName, value);
    204                         _SKIP(attrSize);
    205                         break;
    206                     }
    207                 default:
    208                         ALOGW("ignoring Attribute '%s' unknown type: %d",
    209                               key, attrType);
    210 			_SKIP(attrSize);
    211                         break;
    212             }
    213     }
    214 
    215     // should have consumed it all
    216     if (left != 0) {
    217         ALOGW("did not consume entire buffer; left(%d) != 0", left);
    218 	goto badness;
    219     }
    220 
    221     return mybundle;
    222 
    223   badness:
    224     return NULL;
    225 }
    226 
    227 };  // namespace android
    228 
    229