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 */
40 JNIEXPORT void JNICALL
Java_com_android_tv_tuner_TunerHal_nativeFinalize(JNIEnv *,jobject,jlong deviceId)41 Java_com_android_tv_tuner_TunerHal_nativeFinalize
42 (JNIEnv *, jobject, jlong deviceId) {
43 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
44 if (it != sDvbManagers.end()) {
45 delete it->second;
46 sDvbManagers.erase(it);
47 }
48 }
49
50 /*
51 * Class: com_android_tv_tuner_TunerHal
52 * Method: nativeTune
53 * Signature: (JILjava/lang/String;)Z
54 */
55 JNIEXPORT jboolean JNICALL
Java_com_android_tv_tuner_TunerHal_nativeTune(JNIEnv * env,jobject thiz,jlong deviceId,jint frequency,jstring modulation,jint timeout_ms)56 Java_com_android_tv_tuner_TunerHal_nativeTune
57 (JNIEnv *env, jobject thiz, jlong deviceId, jint frequency, 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,
67 frequency, env->GetStringUTFChars(modulation, 0), timeout_ms);
68 return (res == 0);
69 }
70
71 /*
72 * Class: com_android_tv_tuner_TunerHal
73 * Method: nativeCloseAllPidFilters
74 * Signature: (J)V
75 */
Java_com_android_tv_tuner_TunerHal_nativeCloseAllPidFilters(JNIEnv *,jobject,jlong deviceId)76 JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeCloseAllPidFilters
77 (JNIEnv *, jobject, 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 */
89 JNIEXPORT void JNICALL
Java_com_android_tv_tuner_TunerHal_nativeStopTune(JNIEnv *,jobject,jlong deviceId)90 Java_com_android_tv_tuner_TunerHal_nativeStopTune
91 (JNIEnv *, jobject, jlong deviceId) {
92 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
93 if (it != sDvbManagers.end()) {
94 it->second->stopTune();
95 }
96 }
97
98 /*
99 * Class: com_android_tv_tuner_TunerHal
100 * Method: nativeAddPidFilter
101 * Signature: (JII)V
102 */
103 JNIEXPORT void JNICALL
Java_com_android_tv_tuner_TunerHal_nativeAddPidFilter(JNIEnv * env,jobject thiz,jlong deviceId,jint pid,jint filterType)104 Java_com_android_tv_tuner_TunerHal_nativeAddPidFilter
105 (JNIEnv *env, jobject thiz, jlong deviceId, jint pid, jint filterType) {
106 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
107 if (it != sDvbManagers.end()) {
108 it->second->startTsPidFilter(env, thiz, pid, filterType);
109 }
110 }
111
112 /*
113 * Class: com_android_tv_tuner_TunerHal
114 * Method: nativeWriteInBuffer
115 * Signature: (J[BI)I
116 */
117 JNIEXPORT jint JNICALL
Java_com_android_tv_tuner_TunerHal_nativeWriteInBuffer(JNIEnv * env,jobject thiz,jlong deviceId,jbyteArray javaBuffer,jint javaBufferSize)118 Java_com_android_tv_tuner_TunerHal_nativeWriteInBuffer
119 (JNIEnv *env, jobject thiz, jlong deviceId, jbyteArray javaBuffer, jint javaBufferSize) {
120 uint8_t tsBuffer[TS_PAYLOAD_SIZE];
121 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
122 if (it == sDvbManagers.end()) {
123 return -1;
124 }
125 DvbManager *dvbManager = it->second;
126
127 // Always read multiple of TS_PACKET_SIZE
128 javaBufferSize = (javaBufferSize / TS_PACKET_SIZE) * TS_PACKET_SIZE;
129 int readBufferSize = (javaBufferSize < TS_PAYLOAD_SIZE) ? javaBufferSize : TS_PAYLOAD_SIZE;
130
131 int dataSize = dvbManager->readTsStream(env, thiz, tsBuffer, readBufferSize, 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 * env,jobject thiz,jlong deviceId,jboolean hasPendingTune)151 Java_com_android_tv_tuner_TunerHal_nativeSetHasPendingTune
152 (JNIEnv *env, jobject thiz, 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
166 (JNIEnv *env, jobject thiz, jlong deviceId) {
167 std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
168 if (it != sDvbManagers.end()) {
169 return it->second->getDeliverySystemType(env, thiz);
170 } else {
171 DvbManager *dvbManager = new DvbManager(env, thiz);
172 sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager));
173 return dvbManager->getDeliverySystemType(env, thiz);
174 }
175 }