1 /**
2 * Copyright (C) 2022 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 "libimsmediajni"
18
19 #include <assert.h>
20 #include <utils/Log.h>
21 #include <binder/Parcel.h>
22 #include <android_os_Parcel.h>
23 #include <nativehelper/JNIHelp.h>
24 #include <MediaManagerFactory.h>
25 #include <VideoManager.h>
26 #include <ImsMediaVideoUtil.h>
27 #include <ImsMediaTrace.h>
28 #include <android/native_window_jni.h>
29 #include <android/asset_manager_jni.h>
30
31 #define IMS_MEDIA_JNI_VERSION JNI_VERSION_1_4
32
33 static const char* gClassPath = "com/android/telephony/imsmedia/JNIImsMediaService";
34
35 static JavaVM* gJVM = nullptr;
36 static jclass gClass_JNIImsMediaService = nullptr;
37 static jmethodID gMethod_sendData2Java = nullptr;
38 AAssetManager* gpAssetManager = nullptr;
39
GetJavaVM()40 JavaVM* GetJavaVM()
41 {
42 return gJVM;
43 }
44
SendData2Java(int sessionId,const android::Parcel & objParcel)45 static int SendData2Java(int sessionId, const android::Parcel& objParcel)
46 {
47 JNIEnv* env;
48
49 if ((gClass_JNIImsMediaService == nullptr) || (gMethod_sendData2Java == nullptr))
50 {
51 ALOGE(0, "SendData2Java: Method is null", 0, 0, 0);
52 return 0;
53 }
54
55 JavaVM* jvm = GetJavaVM();
56
57 if (jvm->AttachCurrentThread(&env, nullptr) != JNI_OK)
58 {
59 ALOGE(0, "SendData2Java: AttachCurrentThread fail", 0, 0, 0);
60 return 0;
61 }
62
63 jbyteArray baData = env->NewByteArray(objParcel.dataSize());
64 jbyte* pBuffer = env->GetByteArrayElements(baData, nullptr);
65
66 if (pBuffer != nullptr)
67 {
68 memcpy(pBuffer, objParcel.data(), objParcel.dataSize());
69 env->ReleaseByteArrayElements(baData, pBuffer, 0);
70 env->CallStaticIntMethod(
71 gClass_JNIImsMediaService, gMethod_sendData2Java, sessionId, baData);
72 }
73
74 env->DeleteLocalRef(baData);
75
76 return 1;
77 }
78
setAudioThreadPriority(int threadId)79 void setAudioThreadPriority(int threadId)
80 {
81 JNIEnv* env = nullptr;
82 JavaVM* jvm = GetJavaVM();
83
84 if (gClass_JNIImsMediaService == nullptr)
85 {
86 IMLOGE0("gClass_JNIImsMediaService is null");
87 return;
88 }
89
90 if (jvm == nullptr || jvm->AttachCurrentThread(&env, nullptr) != JNI_OK)
91 {
92 IMLOGE0("setAudioThreadPriority: AttachCurrentThread fail");
93 return;
94 }
95
96 if (env == nullptr)
97 {
98 IMLOGE0("env is null");
99 return;
100 }
101
102 jmethodID gMethod_setAudioThreadPriority =
103 env->GetStaticMethodID(gClass_JNIImsMediaService, "setAudioThreadPriority", "(I)V");
104
105 if (gMethod_setAudioThreadPriority == nullptr)
106 {
107 IMLOGE0("setAudioThreadPriority: GetStaticMethodID gMethod_setAudioThreadPriority failed");
108 return;
109 }
110
111 env->CallStaticIntMethod(gClass_JNIImsMediaService, gMethod_setAudioThreadPriority, threadId);
112 }
113
JNIImsMediaService_getInterface(JNIEnv *,jobject,jint mediatype)114 static jlong JNIImsMediaService_getInterface(
115 JNIEnv* /* env */, jobject /* object */, jint mediatype)
116 {
117 ALOGD("JNIImsMediaService_getInterface: type[%d]", mediatype);
118 BaseManager* manager = nullptr;
119 manager = MediaManagerFactory::getInterface(mediatype);
120 if (manager != nullptr)
121 {
122 manager->setCallback(SendData2Java);
123 }
124
125 return static_cast<jlong>(reinterpret_cast<long>(manager));
126 }
127
JNIImsMediaService_sendMessage(JNIEnv * env,jobject,jlong nativeObj,jint sessionId,jbyteArray baData)128 static void JNIImsMediaService_sendMessage(
129 JNIEnv* env, jobject, jlong nativeObj, jint sessionId, jbyteArray baData)
130 {
131 BaseManager* manager = reinterpret_cast<BaseManager*>(nativeObj);
132 android::Parcel parcel;
133 jbyte* pBuff = env->GetByteArrayElements(baData, nullptr);
134 int nBuffSize = env->GetArrayLength(baData);
135 parcel.setData(reinterpret_cast<const uint8_t*>(pBuff), nBuffSize);
136 parcel.setDataPosition(0);
137
138 if (manager)
139 {
140 manager->sendMessage(sessionId, parcel);
141 }
142
143 env->ReleaseByteArrayElements(baData, pBuff, 0);
144 }
145
JNIImsMediaService_setPreviewSurface(JNIEnv * env,jobject,jlong nativeObj,jint sessionId,jobject surface)146 static void JNIImsMediaService_setPreviewSurface(
147 JNIEnv* env, jobject, jlong nativeObj, jint sessionId, jobject surface)
148 {
149 VideoManager* manager = reinterpret_cast<VideoManager*>(nativeObj);
150
151 if (manager != nullptr)
152 {
153 manager->setPreviewSurface(sessionId, ANativeWindow_fromSurface(env, surface));
154 }
155 }
156
JNIImsMediaService_setDisplaySurface(JNIEnv * env,jobject,jlong nativeObj,jint sessionId,jobject surface)157 static void JNIImsMediaService_setDisplaySurface(
158 JNIEnv* env, jobject, jlong nativeObj, jint sessionId, jobject surface)
159 {
160 VideoManager* manager = reinterpret_cast<VideoManager*>(nativeObj);
161
162 if (manager != nullptr)
163 {
164 manager->setDisplaySurface(sessionId, ANativeWindow_fromSurface(env, surface));
165 }
166 }
167
JNIImsMediaUtil_generateSPROP(JNIEnv * env,jobject,jbyteArray baData)168 static jstring JNIImsMediaUtil_generateSPROP(JNIEnv* env, jobject, jbyteArray baData)
169 {
170 android::Parcel parcel;
171 jbyte* pBuff = env->GetByteArrayElements(baData, nullptr);
172 int nBuffSize = env->GetArrayLength(baData);
173 parcel.setData(reinterpret_cast<const uint8_t*>(pBuff), nBuffSize);
174 parcel.setDataPosition(0);
175
176 VideoConfig videoConfig;
177 videoConfig.readFromParcel(&parcel);
178 env->ReleaseByteArrayElements(baData, pBuff, 0);
179 ALOGE("[GenerateVideoSprop] Profile[%d] level[%d]", videoConfig.getCodecProfile(),
180 videoConfig.getCodecLevel());
181
182 char* sprop = ImsMediaVideoUtil::GenerateVideoSprop(&videoConfig);
183 jstring str = nullptr;
184 if (sprop != nullptr)
185 {
186 str = env->NewStringUTF(sprop);
187 free(sprop);
188 }
189
190 return str;
191 }
192
SetAssetManager(JNIEnv * env,jobject,jobject jobjAssetManager)193 static void SetAssetManager(JNIEnv* env, jobject, jobject jobjAssetManager)
194 {
195 gpAssetManager = AAssetManager_fromJava(env, jobjAssetManager);
196 ALOGD("[SetAssetManager] Asset manager has been set in JNI");
197 }
198
JNIImsMediaService_setLogMode(JNIEnv *,jobject,jint logMode,jint debugLogMode)199 static void JNIImsMediaService_setLogMode(JNIEnv*, jobject, jint logMode, jint debugLogMode)
200 {
201 ImsMediaTrace::IMSetLogMode(logMode);
202 ImsMediaTrace::IMSetDebugLogMode(debugLogMode);
203 }
204
205 static JNINativeMethod gMethods[] = {
206 {"getInterface", "(I)J", (void*)JNIImsMediaService_getInterface},
207 {"sendMessage", "(JI[B)V", (void*)JNIImsMediaService_sendMessage},
208 {"setPreviewSurface", "(JILandroid/view/Surface;)V",
209 (void*)JNIImsMediaService_setPreviewSurface},
210 {"setDisplaySurface", "(JILandroid/view/Surface;)V",
211 (void*)JNIImsMediaService_setDisplaySurface},
212 {"generateSprop", "([B)Ljava/lang/String;", (void*)JNIImsMediaUtil_generateSPROP},
213 {"setAssetManager", "(Landroid/content/res/AssetManager;)V", (void*)SetAssetManager},
214 {"setLogMode", "(II)V", (void*)JNIImsMediaService_setLogMode},
215 };
216
ImsMediaServiceJni_OnLoad(JavaVM * vm,JNIEnv * env)217 jint ImsMediaServiceJni_OnLoad(JavaVM* vm, JNIEnv* env)
218 {
219 gJVM = vm;
220
221 jclass _jclassImsMediaService = env->FindClass(gClassPath);
222
223 if (_jclassImsMediaService == nullptr)
224 {
225 ALOGE("ImsMediaServiceJni_OnLoad :: FindClass failed");
226 return -1;
227 }
228
229 gClass_JNIImsMediaService = reinterpret_cast<jclass>(env->NewGlobalRef(_jclassImsMediaService));
230
231 if (gClass_JNIImsMediaService == nullptr)
232 {
233 ALOGE("ImsMediaServiceJni_OnLoad :: FindClass failed2");
234 return -1;
235 }
236
237 if (jniRegisterNativeMethods(env, gClassPath, gMethods, NELEM(gMethods)) < 0)
238 {
239 ALOGE("ImsMediaServiceJni_OnLoad: RegisterNatives failed");
240 return -1;
241 }
242
243 gMethod_sendData2Java =
244 env->GetStaticMethodID(gClass_JNIImsMediaService, "sendData2Java", "(I[B)I");
245
246 if (gMethod_sendData2Java == nullptr)
247 {
248 ALOGE("ImsMediaServiceJni_OnLoad: GetStaticMethodID failed");
249 return -1;
250 }
251
252 return IMS_MEDIA_JNI_VERSION;
253 }
254