| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "tunertvinput_jni.h" |
| #include <map> |
| |
| #include "DvbManager.h" |
| #define LOG_TAG "tunertvinput_jni" |
| #include "logging.h" |
| |
| //------------------------------------------------------------------------------- |
| // JNI native method implementation |
| //------------------------------------------------------------------------------- |
| |
| #define TS_PACKET_SIZE 188 |
| #define TS_PAYLOAD_SIZE (TS_PACKET_SIZE * 7) // Fit Ethernet MTU (1500) |
| #define READ_TIMEOUT_MS 100 |
| |
| static int sTotalBytesFetched = 0; |
| static std::map<jlong, DvbManager *> sDvbManagers; |
| |
| /* |
| * Class: com_android_tv_tuner_TunerHal |
| * Method: nativeFinalize |
| * Signature: (J)V |
| */ |
| JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeFinalize( |
| JNIEnv *, jobject, jlong deviceId) { |
| std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId); |
| if (it != sDvbManagers.end()) { |
| delete it->second; |
| sDvbManagers.erase(it); |
| } |
| } |
| |
| /* |
| * Class: com_android_tv_tuner_TunerHal |
| * Method: nativeTune |
| * Signature: (JILjava/lang/String;)Z |
| */ |
| JNIEXPORT jboolean JNICALL Java_com_android_tv_tuner_TunerHal_nativeTune( |
| JNIEnv *env, jobject thiz, jlong deviceId, jint frequency, |
| jstring modulation, jint timeout_ms) { |
| std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId); |
| DvbManager *dvbManager; |
| if (it == sDvbManagers.end()) { |
| dvbManager = new DvbManager(env, thiz); |
| sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager)); |
| } else { |
| dvbManager = it->second; |
| } |
| int res = dvbManager->tune(env, thiz, frequency, |
| env->GetStringUTFChars(modulation, 0), timeout_ms); |
| return (res == 0); |
| } |
| |
| /* |
| * Class: com_android_tv_tuner_TunerHal |
| * Method: nativeCloseAllPidFilters |
| * Signature: (J)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_com_android_tv_tuner_TunerHal_nativeCloseAllPidFilters(JNIEnv *, jobject, |
| jlong deviceId) { |
| std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId); |
| if (it != sDvbManagers.end()) { |
| it->second->closeAllDvbPidFilter(); |
| } |
| } |
| |
| /* |
| * Class: com_android_tv_tuner_TunerHal |
| * Method: nativeStopTune |
| * Signature: (J)V |
| */ |
| JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeStopTune( |
| JNIEnv *, jobject, jlong deviceId) { |
| std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId); |
| if (it != sDvbManagers.end()) { |
| it->second->stopTune(); |
| } |
| } |
| |
| /* |
| * Class: com_android_tv_tuner_TunerHal |
| * Method: nativeGetSignalStrength |
| * Signature: (J)V |
| */ |
| JNIEXPORT int JNICALL |
| Java_com_android_tv_tuner_TunerHal_nativeGetSignalStrength( |
| JNIEnv *, jobject, jlong deviceId) { |
| std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId); |
| if (it != sDvbManagers.end()) { |
| return it->second->getSignalStrength(); |
| } |
| // If DvbManager can't be found, |
| // return -3 as signal strength not supported. |
| return -3; |
| } |
| |
| /* |
| * Class: com_android_tv_tuner_TunerHal |
| * Method: nativeAddPidFilter |
| * Signature: (JII)V |
| */ |
| JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeAddPidFilter( |
| JNIEnv *env, jobject thiz, jlong deviceId, jint pid, jint filterType) { |
| std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId); |
| if (it != sDvbManagers.end()) { |
| it->second->startTsPidFilter(env, thiz, pid, filterType); |
| } |
| } |
| |
| /* |
| * Class: com_android_tv_tuner_TunerHal |
| * Method: nativeWriteInBuffer |
| * Signature: (J[BI)I |
| */ |
| JNIEXPORT jint JNICALL Java_com_android_tv_tuner_TunerHal_nativeWriteInBuffer( |
| JNIEnv *env, jobject thiz, jlong deviceId, jbyteArray javaBuffer, |
| jint javaBufferSize) { |
| uint8_t tsBuffer[TS_PAYLOAD_SIZE]; |
| std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId); |
| if (it == sDvbManagers.end()) { |
| return -1; |
| } |
| DvbManager *dvbManager = it->second; |
| |
| // Always read multiple of TS_PACKET_SIZE |
| javaBufferSize = (javaBufferSize / TS_PACKET_SIZE) * TS_PACKET_SIZE; |
| int readBufferSize = |
| (javaBufferSize < TS_PAYLOAD_SIZE) ? javaBufferSize : TS_PAYLOAD_SIZE; |
| |
| int dataSize = dvbManager->readTsStream(env, thiz, tsBuffer, readBufferSize, |
| READ_TIMEOUT_MS); |
| if (dataSize == 0) { |
| ALOGD("No data to read DVR"); |
| return 0; |
| } else if (dataSize < 0) { |
| return -1; |
| } |
| |
| sTotalBytesFetched += dataSize; |
| |
| env->SetByteArrayRegion(javaBuffer, 0, dataSize, (jbyte *)tsBuffer); |
| return dataSize; |
| } |
| |
| /* |
| * Class: com_android_tv_tuner_TunerHal |
| * Method: nativeSetHasPendingTune |
| * Signature: (JZ)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_com_android_tv_tuner_TunerHal_nativeSetHasPendingTune( |
| JNIEnv *, jobject, jlong deviceId, jboolean hasPendingTune) { |
| std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId); |
| if (it != sDvbManagers.end()) { |
| it->second->setHasPendingTune(hasPendingTune); |
| } |
| } |
| |
| /* |
| * Class: com_android_tv_tuner_TunerHal |
| * Method: nativeGetDeliverySystemType |
| * Signature: (J)I |
| */ |
| JNIEXPORT int JNICALL |
| Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemType(JNIEnv *env, |
| jobject thiz, |
| jlong deviceId) { |
| std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId); |
| if (it != sDvbManagers.end()) { |
| return it->second->getDeliverySystemType(env, thiz); |
| } else { |
| DvbManager *dvbManager = new DvbManager(env, thiz); |
| sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager)); |
| return dvbManager->getDeliverySystemType(env, thiz); |
| } |
| } |