1 /*
2  * Copyright 2014 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 "TvInputHal"
18 
19 //#define LOG_NDEBUG 0
20 
21 #include "tvinput/JTvInputHal.h"
22 
23 gBundleClassInfoType gBundleClassInfo;
24 gTvInputHalClassInfoType gTvInputHalClassInfo;
25 gTvStreamConfigClassInfoType gTvStreamConfigClassInfo;
26 gTvStreamConfigBuilderClassInfoType gTvStreamConfigBuilderClassInfo;
27 gTvInputHardwareInfoBuilderClassInfoType gTvInputHardwareInfoBuilderClassInfo;
28 
29 namespace android {
30 
nativeOpen(JNIEnv * env,jobject thiz,jobject messageQueueObj)31 static jlong nativeOpen(JNIEnv* env, jobject thiz, jobject messageQueueObj) {
32     sp<MessageQueue> messageQueue =
33             android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
34     return (jlong)JTvInputHal::createInstance(env, thiz, messageQueue->getLooper());
35 }
36 
nativeAddOrUpdateStream(JNIEnv * env,jclass clazz,jlong ptr,jint deviceId,jint streamId,jobject jsurface)37 static int nativeAddOrUpdateStream(JNIEnv* env, jclass clazz,
38         jlong ptr, jint deviceId, jint streamId, jobject jsurface) {
39     JTvInputHal* tvInputHal = (JTvInputHal*)ptr;
40     if (!jsurface) {
41         return BAD_VALUE;
42     }
43     sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
44     if (!Surface::isValid(surface)) {
45         return BAD_VALUE;
46     }
47     return tvInputHal->addOrUpdateStream(deviceId, streamId, surface);
48 }
49 
nativeRemoveStream(JNIEnv * env,jclass clazz,jlong ptr,jint deviceId,jint streamId)50 static int nativeRemoveStream(JNIEnv* env, jclass clazz,
51         jlong ptr, jint deviceId, jint streamId) {
52     JTvInputHal* tvInputHal = (JTvInputHal*)ptr;
53     return tvInputHal->removeStream(deviceId, streamId);
54 }
55 
nativeGetStreamConfigs(JNIEnv * env,jclass clazz,jlong ptr,jint deviceId,jint generation)56 static jobjectArray nativeGetStreamConfigs(JNIEnv* env, jclass clazz,
57         jlong ptr, jint deviceId, jint generation) {
58     JTvInputHal* tvInputHal = (JTvInputHal*)ptr;
59     const std::vector<AidlTvStreamConfig> configs = tvInputHal->getStreamConfigs(deviceId);
60 
61     jobjectArray result = env->NewObjectArray(configs.size(), gTvStreamConfigClassInfo.clazz, NULL);
62     for (size_t i = 0; i < configs.size(); ++i) {
63         jobject builder = env->NewObject(
64                 gTvStreamConfigBuilderClassInfo.clazz,
65                 gTvStreamConfigBuilderClassInfo.constructor);
66         env->CallObjectMethod(
67                 builder, gTvStreamConfigBuilderClassInfo.streamId, configs[i].streamId);
68         env->CallObjectMethod(
69                 builder, gTvStreamConfigBuilderClassInfo.type,
70                         TV_STREAM_TYPE_INDEPENDENT_VIDEO_SOURCE);
71         env->CallObjectMethod(
72                 builder, gTvStreamConfigBuilderClassInfo.maxWidth, configs[i].maxVideoWidth);
73         env->CallObjectMethod(
74                 builder, gTvStreamConfigBuilderClassInfo.maxHeight, configs[i].maxVideoHeight);
75         env->CallObjectMethod(
76                 builder, gTvStreamConfigBuilderClassInfo.generation, generation);
77 
78         jobject config = env->CallObjectMethod(builder, gTvStreamConfigBuilderClassInfo.build);
79 
80         env->SetObjectArrayElement(result, i, config);
81 
82         env->DeleteLocalRef(config);
83         env->DeleteLocalRef(builder);
84     }
85     return result;
86 }
87 
nativeSetTvMessageEnabled(JNIEnv * env,jclass clazz,jlong ptr,jint deviceId,jint streamId,jint type,jboolean enabled)88 static int nativeSetTvMessageEnabled(JNIEnv* env, jclass clazz, jlong ptr, jint deviceId,
89                                      jint streamId, jint type, jboolean enabled) {
90     JTvInputHal* tvInputHal = (JTvInputHal*)ptr;
91     return tvInputHal->setTvMessageEnabled(deviceId, streamId, type, enabled);
92 }
93 
nativeClose(JNIEnv * env,jclass clazz,jlong ptr)94 static void nativeClose(JNIEnv* env, jclass clazz, jlong ptr) {
95     JTvInputHal* tvInputHal = (JTvInputHal*)ptr;
96     delete tvInputHal;
97 }
98 
99 static const JNINativeMethod gTvInputHalMethods[] = {
100         /* name, signature, funcPtr */
101         {"nativeOpen", "(Landroid/os/MessageQueue;)J", (void*)nativeOpen},
102         {"nativeAddOrUpdateStream", "(JIILandroid/view/Surface;)I", (void*)nativeAddOrUpdateStream},
103         {"nativeRemoveStream", "(JII)I", (void*)nativeRemoveStream},
104         {"nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;",
105          (void*)nativeGetStreamConfigs},
106         {"nativeSetTvMessageEnabled", "(JIIIZ)I", (void*)nativeSetTvMessageEnabled},
107         {"nativeClose", "(J)V", (void*)nativeClose},
108 };
109 
110 #define FIND_CLASS(var, className) \
111         var = env->FindClass(className); \
112         LOG_FATAL_IF(! (var), "Unable to find class " className)
113 
114 #define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
115         var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
116         LOG_FATAL_IF(! (var), "Unable to find method" methodName)
117 
register_android_server_tv_TvInputHal(JNIEnv * env)118 int register_android_server_tv_TvInputHal(JNIEnv* env) {
119     int res = jniRegisterNativeMethods(env, "com/android/server/tv/TvInputHal",
120             gTvInputHalMethods, NELEM(gTvInputHalMethods));
121     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
122     (void)res; // Don't complain about unused variable in the LOG_NDEBUG case
123 
124     jclass clazz;
125     FIND_CLASS(clazz, "com/android/server/tv/TvInputHal");
126 
127     GET_METHOD_ID(
128             gTvInputHalClassInfo.deviceAvailable, clazz,
129             "deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V");
130     GET_METHOD_ID(
131             gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V");
132     GET_METHOD_ID(gTvInputHalClassInfo.streamConfigsChanged, clazz,
133                   "streamConfigsChangedFromNative", "(II)V");
134     GET_METHOD_ID(
135             gTvInputHalClassInfo.firstFrameCaptured, clazz,
136             "firstFrameCapturedFromNative", "(II)V");
137     GET_METHOD_ID(gTvInputHalClassInfo.tvMessageReceived, clazz, "tvMessageReceivedFromNative",
138                   "(IILandroid/os/Bundle;)V");
139 
140     FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/media/tv/TvStreamConfig");
141     gTvStreamConfigClassInfo.clazz = jclass(env->NewGlobalRef(gTvStreamConfigClassInfo.clazz));
142 
143     FIND_CLASS(gBundleClassInfo.clazz, "android/os/Bundle");
144     gBundleClassInfo.clazz = jclass(env->NewGlobalRef(gBundleClassInfo.clazz));
145     GET_METHOD_ID(gBundleClassInfo.constructor, gBundleClassInfo.clazz, "<init>", "()V");
146     GET_METHOD_ID(gBundleClassInfo.putByteArray, gBundleClassInfo.clazz, "putByteArray",
147                   "(Ljava/lang/String;[B)V");
148     GET_METHOD_ID(gBundleClassInfo.putString, gBundleClassInfo.clazz, "putString",
149                   "(Ljava/lang/String;Ljava/lang/String;)V");
150     GET_METHOD_ID(gBundleClassInfo.putInt, gBundleClassInfo.clazz, "putInt",
151                   "(Ljava/lang/String;I)V");
152 
153     FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/media/tv/TvStreamConfig$Builder");
154     gTvStreamConfigBuilderClassInfo.clazz =
155             jclass(env->NewGlobalRef(gTvStreamConfigBuilderClassInfo.clazz));
156 
157     GET_METHOD_ID(
158             gTvStreamConfigBuilderClassInfo.constructor,
159             gTvStreamConfigBuilderClassInfo.clazz,
160             "<init>", "()V");
161     GET_METHOD_ID(
162             gTvStreamConfigBuilderClassInfo.streamId,
163             gTvStreamConfigBuilderClassInfo.clazz,
164             "streamId", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
165     GET_METHOD_ID(
166             gTvStreamConfigBuilderClassInfo.type,
167             gTvStreamConfigBuilderClassInfo.clazz,
168             "type", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
169     GET_METHOD_ID(
170             gTvStreamConfigBuilderClassInfo.maxWidth,
171             gTvStreamConfigBuilderClassInfo.clazz,
172             "maxWidth", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
173     GET_METHOD_ID(
174             gTvStreamConfigBuilderClassInfo.maxHeight,
175             gTvStreamConfigBuilderClassInfo.clazz,
176             "maxHeight", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
177     GET_METHOD_ID(
178             gTvStreamConfigBuilderClassInfo.generation,
179             gTvStreamConfigBuilderClassInfo.clazz,
180             "generation", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
181     GET_METHOD_ID(
182             gTvStreamConfigBuilderClassInfo.build,
183             gTvStreamConfigBuilderClassInfo.clazz,
184             "build", "()Landroid/media/tv/TvStreamConfig;");
185 
186     FIND_CLASS(gTvInputHardwareInfoBuilderClassInfo.clazz,
187             "android/media/tv/TvInputHardwareInfo$Builder");
188     gTvInputHardwareInfoBuilderClassInfo.clazz =
189             jclass(env->NewGlobalRef(gTvInputHardwareInfoBuilderClassInfo.clazz));
190 
191     GET_METHOD_ID(
192             gTvInputHardwareInfoBuilderClassInfo.constructor,
193             gTvInputHardwareInfoBuilderClassInfo.clazz,
194             "<init>", "()V");
195     GET_METHOD_ID(
196             gTvInputHardwareInfoBuilderClassInfo.deviceId,
197             gTvInputHardwareInfoBuilderClassInfo.clazz,
198             "deviceId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
199     GET_METHOD_ID(
200             gTvInputHardwareInfoBuilderClassInfo.type,
201             gTvInputHardwareInfoBuilderClassInfo.clazz,
202             "type", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
203     GET_METHOD_ID(
204             gTvInputHardwareInfoBuilderClassInfo.hdmiPortId,
205             gTvInputHardwareInfoBuilderClassInfo.clazz,
206             "hdmiPortId", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
207     GET_METHOD_ID(
208             gTvInputHardwareInfoBuilderClassInfo.cableConnectionStatus,
209             gTvInputHardwareInfoBuilderClassInfo.clazz,
210             "cableConnectionStatus", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
211     GET_METHOD_ID(
212             gTvInputHardwareInfoBuilderClassInfo.audioType,
213             gTvInputHardwareInfoBuilderClassInfo.clazz,
214             "audioType", "(I)Landroid/media/tv/TvInputHardwareInfo$Builder;");
215     GET_METHOD_ID(
216             gTvInputHardwareInfoBuilderClassInfo.audioAddress,
217             gTvInputHardwareInfoBuilderClassInfo.clazz,
218             "audioAddress", "(Ljava/lang/String;)Landroid/media/tv/TvInputHardwareInfo$Builder;");
219     GET_METHOD_ID(
220             gTvInputHardwareInfoBuilderClassInfo.build,
221             gTvInputHardwareInfoBuilderClassInfo.clazz,
222             "build", "()Landroid/media/tv/TvInputHardwareInfo;");
223 
224     return 0;
225 }
226 
227 } /* namespace android */
228