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;)Z
53 */
Java_com_android_tv_tuner_TunerHal_nativeTune(JNIEnv * env,jobject thiz,jlong deviceId,jint frequency,jstring modulation,jint timeout_ms)54 JNIEXPORT jboolean JNICALL Java_com_android_tv_tuner_TunerHal_nativeTune(
55 JNIEnv *env, jobject thiz, jlong deviceId, jint frequency,
56 jstring modulation, jint timeout_ms) {
57 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
58 DvbManager *dvbManager;
59 if (it == sDvbManagers.end()) {
60 dvbManager = new DvbManager(env, thiz);
61 sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager));
62 } else {
63 dvbManager = it->second;
64 }
65 int res = dvbManager->tune(env, thiz, frequency,
66 env->GetStringUTFChars(modulation, 0), timeout_ms);
67 return (res == 0);
68 }
69
70 /*
71 * Class: com_android_tv_tuner_TunerHal
72 * Method: nativeCloseAllPidFilters
73 * Signature: (J)V
74 */
75 JNIEXPORT void JNICALL
Java_com_android_tv_tuner_TunerHal_nativeCloseAllPidFilters(JNIEnv *,jobject,jlong deviceId)76 Java_com_android_tv_tuner_TunerHal_nativeCloseAllPidFilters(JNIEnv *, jobject,
77 jlong deviceId) {
78 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
79 if (it != sDvbManagers.end()) {
80 it->second->closeAllDvbPidFilter();
81 }
82 }
83
84 /*
85 * Class: com_android_tv_tuner_TunerHal
86 * Method: nativeStopTune
87 * Signature: (J)V
88 */
Java_com_android_tv_tuner_TunerHal_nativeStopTune(JNIEnv *,jobject,jlong deviceId)89 JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeStopTune(
90 JNIEnv *, jobject, jlong deviceId) {
91 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
92 if (it != sDvbManagers.end()) {
93 it->second->stopTune();
94 }
95 }
96
97 /*
98 * Class: com_android_tv_tuner_TunerHal
99 * Method: nativeAddPidFilter
100 * Signature: (JII)V
101 */
Java_com_android_tv_tuner_TunerHal_nativeAddPidFilter(JNIEnv * env,jobject thiz,jlong deviceId,jint pid,jint filterType)102 JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeAddPidFilter(
103 JNIEnv *env, jobject thiz, jlong deviceId, jint pid, jint filterType) {
104 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
105 if (it != sDvbManagers.end()) {
106 it->second->startTsPidFilter(env, thiz, pid, filterType);
107 }
108 }
109
110 /*
111 * Class: com_android_tv_tuner_TunerHal
112 * Method: nativeWriteInBuffer
113 * Signature: (J[BI)I
114 */
Java_com_android_tv_tuner_TunerHal_nativeWriteInBuffer(JNIEnv * env,jobject thiz,jlong deviceId,jbyteArray javaBuffer,jint javaBufferSize)115 JNIEXPORT jint JNICALL Java_com_android_tv_tuner_TunerHal_nativeWriteInBuffer(
116 JNIEnv *env, jobject thiz, jlong deviceId, jbyteArray javaBuffer,
117 jint javaBufferSize) {
118 uint8_t tsBuffer[TS_PAYLOAD_SIZE];
119 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
120 if (it == sDvbManagers.end()) {
121 return -1;
122 }
123 DvbManager *dvbManager = it->second;
124
125 // Always read multiple of TS_PACKET_SIZE
126 javaBufferSize = (javaBufferSize / TS_PACKET_SIZE) * TS_PACKET_SIZE;
127 int readBufferSize =
128 (javaBufferSize < TS_PAYLOAD_SIZE) ? javaBufferSize : TS_PAYLOAD_SIZE;
129
130 int dataSize = dvbManager->readTsStream(env, thiz, tsBuffer, readBufferSize,
131 READ_TIMEOUT_MS);
132 if (dataSize == 0) {
133 ALOGD("No data to read DVR");
134 return 0;
135 } else if (dataSize < 0) {
136 return -1;
137 }
138
139 sTotalBytesFetched += dataSize;
140
141 env->SetByteArrayRegion(javaBuffer, 0, dataSize, (jbyte *)tsBuffer);
142 return dataSize;
143 }
144
145 /*
146 * Class: com_android_tv_tuner_TunerHal
147 * Method: nativeSetHasPendingTune
148 * Signature: (JZ)V
149 */
150 JNIEXPORT void JNICALL
Java_com_android_tv_tuner_TunerHal_nativeSetHasPendingTune(JNIEnv *,jobject,jlong deviceId,jboolean hasPendingTune)151 Java_com_android_tv_tuner_TunerHal_nativeSetHasPendingTune(
152 JNIEnv *, jobject, jlong deviceId, jboolean hasPendingTune) {
153 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
154 if (it != sDvbManagers.end()) {
155 it->second->setHasPendingTune(hasPendingTune);
156 }
157 }
158
159 /*
160 * Class: com_android_tv_tuner_TunerHal
161 * Method: nativeGetDeliverySystemType
162 * Signature: (J)I
163 */
164 JNIEXPORT int JNICALL
Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemType(JNIEnv * env,jobject thiz,jlong deviceId)165 Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemType(JNIEnv *env,
166 jobject thiz,
167 jlong deviceId) {
168 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
169 if (it != sDvbManagers.end()) {
170 return it->second->getDeliverySystemType(env, thiz);
171 } else {
172 DvbManager *dvbManager = new DvbManager(env, thiz);
173 sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager));
174 return dvbManager->getDeliverySystemType(env, thiz);
175 }
176 }