1 /*
2 * Copyright (C) 2015 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 #include "tunertvinput_jni.h"
18 #include <map>
19
20 #include "DvbManager.h"
21 #define LOG_TAG "tunertvinput_jni"
22 #include "logging.h"
23
24 //-------------------------------------------------------------------------------
25 // JNI native method implementation
26 //-------------------------------------------------------------------------------
27
28 #define TS_PACKET_SIZE 188
29 #define TS_PAYLOAD_SIZE (TS_PACKET_SIZE * 7) // Fit Ethernet MTU (1500)
30 #define READ_TIMEOUT_MS 100
31
32 static int sTotalBytesFetched = 0;
33 static std::map<jlong, DvbManager *> sDvbManagers;
34
35 /*
36 * Class: com_android_tv_tuner_TunerHal
37 * Method: nativeFinalize
38 * Signature: (J)V
39 */
Java_com_android_tv_tuner_TunerHal_nativeFinalize(JNIEnv *,jobject,jlong deviceId)40 JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeFinalize(
41 JNIEnv *, jobject, jlong deviceId) {
42 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
43 if (it != sDvbManagers.end()) {
44 delete it->second;
45 sDvbManagers.erase(it);
46 }
47 }
48
49 /*
50 * Class: com_android_tv_tuner_TunerHal
51 * Method: nativeTune
52 * Signature: (JILjava/lang/String;I)Z
53 */
54 JNIEXPORT jboolean JNICALL
Java_com_android_tv_tuner_TunerHal_nativeTune__JILjava_lang_String_2I(JNIEnv * env,jobject thiz,jlong deviceId,jint frequency,jstring modulation,jint timeout_ms)55 Java_com_android_tv_tuner_TunerHal_nativeTune__JILjava_lang_String_2I(
56 JNIEnv *env, jobject thiz, jlong deviceId, jint frequency,
57 jstring modulation, jint timeout_ms) {
58 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
59 DvbManager *dvbManager;
60 if (it == sDvbManagers.end()) {
61 dvbManager = new DvbManager(env, thiz);
62 sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager));
63 } else {
64 dvbManager = it->second;
65 }
66 int res = dvbManager->tune(env, thiz, frequency,
67 env->GetStringUTFChars(modulation, 0), timeout_ms);
68 return (res == 0);
69 }
70
71 /*
72 * Class: com_android_tv_tuner_TunerHal
73 * Method: nativeTune
74 * Signature: (JIILjava/lang/String;I)Z
75 */
76 JNIEXPORT jboolean JNICALL
Java_com_android_tv_tuner_TunerHal_nativeTune__JIILjava_lang_String_2I(JNIEnv * env,jobject thiz,jlong deviceId,jint deliverySystemType,jint frequency,jstring modulation,jint timeout_ms)77 Java_com_android_tv_tuner_TunerHal_nativeTune__JIILjava_lang_String_2I(
78 JNIEnv *env, jobject thiz, jlong deviceId, jint deliverySystemType,
79 jint frequency, jstring modulation, jint timeout_ms) {
80 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
81 DvbManager *dvbManager;
82 if (it == sDvbManagers.end()) {
83 dvbManager = new DvbManager(env, thiz);
84 sDvbManagers.insert(
85 std::pair<jlong, DvbManager *>(deviceId, dvbManager));
86 } else {
87 dvbManager = it->second;
88 }
89 int res = dvbManager->tune(env, thiz, deliverySystemType, frequency,
90 env->GetStringUTFChars(modulation, 0), timeout_ms);
91 return (res == 0);
92 }
93
94 /*
95 * Class: com_android_tv_tuner_TunerHal
96 * Method: nativeCloseAllPidFilters
97 * Signature: (J)V
98 */
99 JNIEXPORT void JNICALL
Java_com_android_tv_tuner_TunerHal_nativeCloseAllPidFilters(JNIEnv *,jobject,jlong deviceId)100 Java_com_android_tv_tuner_TunerHal_nativeCloseAllPidFilters(JNIEnv *, jobject,
101 jlong deviceId) {
102 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
103 if (it != sDvbManagers.end()) {
104 it->second->closeAllDvbPidFilter();
105 }
106 }
107
108 /*
109 * Class: com_android_tv_tuner_TunerHal
110 * Method: nativeStopTune
111 * Signature: (J)V
112 */
Java_com_android_tv_tuner_TunerHal_nativeStopTune(JNIEnv *,jobject,jlong deviceId)113 JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeStopTune(
114 JNIEnv *, jobject, jlong deviceId) {
115 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
116 if (it != sDvbManagers.end()) {
117 it->second->stopTune();
118 }
119 }
120
121 /*
122 * Class: com_android_tv_tuner_TunerHal
123 * Method: nativeGetSignalStrength
124 * Signature: (J)V
125 */
126 JNIEXPORT int JNICALL
Java_com_android_tv_tuner_TunerHal_nativeGetSignalStrength(JNIEnv *,jobject,jlong deviceId)127 Java_com_android_tv_tuner_TunerHal_nativeGetSignalStrength(
128 JNIEnv *, jobject, jlong deviceId) {
129 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
130 if (it != sDvbManagers.end()) {
131 return it->second->getSignalStrength();
132 }
133 // If DvbManager can't be found,
134 // return -3 as signal strength not supported.
135 return -3;
136 }
137
138 /*
139 * Class: com_android_tv_tuner_TunerHal
140 * Method: nativeAddPidFilter
141 * Signature: (JII)V
142 */
Java_com_android_tv_tuner_TunerHal_nativeAddPidFilter(JNIEnv * env,jobject thiz,jlong deviceId,jint pid,jint filterType)143 JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeAddPidFilter(
144 JNIEnv *env, jobject thiz, jlong deviceId, jint pid, jint filterType) {
145 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
146 if (it != sDvbManagers.end()) {
147 it->second->startTsPidFilter(env, thiz, pid, filterType);
148 }
149 }
150
151 /*
152 * Class: com_android_tv_tuner_TunerHal
153 * Method: nativeWriteInBuffer
154 * Signature: (J[BI)I
155 */
Java_com_android_tv_tuner_TunerHal_nativeWriteInBuffer(JNIEnv * env,jobject thiz,jlong deviceId,jbyteArray javaBuffer,jint javaBufferSize)156 JNIEXPORT jint JNICALL Java_com_android_tv_tuner_TunerHal_nativeWriteInBuffer(
157 JNIEnv *env, jobject thiz, jlong deviceId, jbyteArray javaBuffer,
158 jint javaBufferSize) {
159 uint8_t tsBuffer[TS_PAYLOAD_SIZE];
160 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
161 if (it == sDvbManagers.end()) {
162 return -1;
163 }
164 DvbManager *dvbManager = it->second;
165
166 // Always read multiple of TS_PACKET_SIZE
167 javaBufferSize = (javaBufferSize / TS_PACKET_SIZE) * TS_PACKET_SIZE;
168 int readBufferSize =
169 (javaBufferSize < TS_PAYLOAD_SIZE) ? javaBufferSize : TS_PAYLOAD_SIZE;
170
171 int dataSize = dvbManager->readTsStream(env, thiz, tsBuffer, readBufferSize,
172 READ_TIMEOUT_MS);
173 if (dataSize == 0) {
174 ALOGD("No data to read DVR");
175 return 0;
176 } else if (dataSize < 0) {
177 return -1;
178 }
179
180 sTotalBytesFetched += dataSize;
181
182 env->SetByteArrayRegion(javaBuffer, 0, dataSize, (jbyte *)tsBuffer);
183 return dataSize;
184 }
185
186 /*
187 * Class: com_android_tv_tuner_TunerHal
188 * Method: nativeSetHasPendingTune
189 * Signature: (JZ)V
190 */
191 JNIEXPORT void JNICALL
Java_com_android_tv_tuner_TunerHal_nativeSetHasPendingTune(JNIEnv *,jobject,jlong deviceId,jboolean hasPendingTune)192 Java_com_android_tv_tuner_TunerHal_nativeSetHasPendingTune(
193 JNIEnv *, jobject, jlong deviceId, jboolean hasPendingTune) {
194 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
195 if (it != sDvbManagers.end()) {
196 it->second->setHasPendingTune(hasPendingTune);
197 }
198 }
199
200 /*
201 * Class: com_android_tv_tuner_TunerHal
202 * Method: nativeGetDeliverySystemType
203 * Signature: (J)I
204 */
205 JNIEXPORT int JNICALL
Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemType(JNIEnv * env,jobject thiz,jlong deviceId)206 Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemType(JNIEnv *env,
207 jobject thiz,
208 jlong deviceId) {
209 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
210 if (it != sDvbManagers.end()) {
211 return it->second->getDeliverySystemType(env, thiz);
212 } else {
213 DvbManager *dvbManager = new DvbManager(env, thiz);
214 sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager));
215 return dvbManager->getDeliverySystemType(env, thiz);
216 }
217 }
218
219 /*
220 * Class: com_android_tv_tuner_TunerHal
221 * Method: nativeGetDeliverySystemTypes
222 * Signature: (J)I
223 */
224 JNIEXPORT jintArray JNICALL
Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemTypes(JNIEnv * env,jobject thiz,jlong deviceId)225 Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemTypes(JNIEnv *env,
226 jobject thiz,
227 jlong deviceId) {
228 jintArray deliverySystemTypes = env->NewIntArray(8);
229 if (deliverySystemTypes == NULL) {
230 ALOGE("Out of memory!");
231 return NULL;
232 }
233 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
234 if (it != sDvbManagers.end()) {
235 env->SetIntArrayRegion(deliverySystemTypes, 0, 8,
236 it->second->getDeliverySystemTypes(env, thiz));
237 } else {
238 DvbManager *dvbManager = new DvbManager(env, thiz);
239 sDvbManagers.insert(
240 std::pair<jlong, DvbManager *>(deviceId, dvbManager));
241 env->SetIntArrayRegion(deliverySystemTypes, 0, 8,
242 dvbManager->getDeliverySystemTypes(env, thiz));
243 }
244 return deliverySystemTypes;
245 }
246