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