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_usbtuner_TunerHal
37  * Method:    nativeFinalize
38  * Signature: (J)V
39  */
40 JNIEXPORT void JNICALL
Java_com_android_usbtuner_TunerHal_nativeFinalize(JNIEnv *,jobject,jlong deviceId)41 Java_com_android_usbtuner_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_usbtuner_TunerHal
52  * Method:    nativeTune
53  * Signature: (JILjava/lang/String;)Z
54  */
55 JNIEXPORT jboolean JNICALL
Java_com_android_usbtuner_TunerHal_nativeTune(JNIEnv * env,jobject thiz,jlong deviceId,jint frequency,jstring modulation,jint timeout_ms)56 Java_com_android_usbtuner_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_usbtuner_TunerHal
73  * Method:    nativeCloseAllPidFilters
74  * Signature: (J)V
75  */
Java_com_android_usbtuner_TunerHal_nativeCloseAllPidFilters(JNIEnv *,jobject,jlong deviceId)76 JNIEXPORT void JNICALL Java_com_android_usbtuner_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_usbtuner_TunerHal
86  * Method:    nativeStopTune
87  * Signature: (J)V
88  */
89 JNIEXPORT void JNICALL
Java_com_android_usbtuner_TunerHal_nativeStopTune(JNIEnv *,jobject,jlong deviceId)90 Java_com_android_usbtuner_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_usbtuner_TunerHal
100  * Method:    nativeAddPidFilter
101  * Signature: (JII)V
102  */
103 JNIEXPORT void JNICALL
Java_com_android_usbtuner_TunerHal_nativeAddPidFilter(JNIEnv * env,jobject thiz,jlong deviceId,jint pid,jint filterType)104 Java_com_android_usbtuner_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_usbtuner_TunerHal
114  * Method:    nativeWriteInBuffer
115  * Signature: (J[BI)I
116  */
117 JNIEXPORT jint JNICALL
Java_com_android_usbtuner_TunerHal_nativeWriteInBuffer(JNIEnv * env,jobject thiz,jlong deviceId,jbyteArray javaBuffer,jint javaBufferSize)118 Java_com_android_usbtuner_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