blob: de60b085b87d979d8774ab57a5fae0adc84f6a74 [file] [log] [blame]
Dongwon Kangbf98d542018-09-11 14:40:23 -07001/*
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
Ray Essickc535a552019-01-18 11:38:15 -080017#define LOG_TAG "MediaMetricsJNI"
18
Dongwon Kangbf98d542018-09-11 14:40:23 -070019#include <jni.h>
20#include <nativehelper/JNIHelp.h>
21
22#include "android_media_MediaMetricsJNI.h"
23#include <media/MediaAnalyticsItem.h>
24
25
Ray Essickc535a552019-01-18 11:38:15 -080026// This source file is compiled and linked into both:
27// core/jni/ (libandroid_runtime.so)
28// media/jni (libmedia2_jni.so)
29
Dongwon Kangbf98d542018-09-11 14:40:23 -070030namespace android {
31
32// place the attributes into a java PersistableBundle object
33jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
34
35 jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
36 if (clazzBundle==NULL) {
Ray Essickc535a552019-01-18 11:38:15 -080037 ALOGE("can't find android/os/PersistableBundle");
Dongwon Kangbf98d542018-09-11 14:40:23 -070038 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
Ray Essickc535a552019-01-18 11:38:15 -080094// 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
99enum { kInt32 = 0, kInt64, kDouble, kRate, kCString};
100
101jobject 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
Dongwon Kangbf98d542018-09-11 14:40:23 -0700227}; // namespace android
228