From 5fd699452a78ec128ec22e79249544045a5dc41c Mon Sep 17 00:00:00 2001 From: sadiqsada Date: Thu, 26 Jan 2023 17:27:27 -0800 Subject: [PATCH] Add JNI for IPTV Test: m Bug: 266287614 Change-Id: Ie4168462a2b0caf6aa70fb326e0df813ac552c9c --- media/java/android/media/tv/tuner/Tuner.java | 7 + media/jni/android_media_tv_Tuner.cpp | 165 +++++++++++++------ 2 files changed, 121 insertions(+), 51 deletions(-) diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index ac920d2703589..7d08b81fd1562 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -1297,6 +1297,13 @@ public class Tuner implements AutoCloseable { return RESULT_UNAVAILABLE; } } + if (mFrontendType == FrontendSettings.TYPE_IPTV) { + if (!TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_3_0, + "Tuner with IPTV Frontend")) { + return RESULT_UNAVAILABLE; + } + } if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND, mFrontendLock)) { mScanCallback = scanCallback; diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index 35ee3ee969e69..625e842a2db91 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -132,6 +132,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -283,6 +288,11 @@ using ::aidl::android::hardware::tv::tuner::FrontendIsdbtModulation; using ::aidl::android::hardware::tv::tuner::FrontendIsdbtPartialReceptionFlag; using ::aidl::android::hardware::tv::tuner::FrontendIsdbtSettings; using ::aidl::android::hardware::tv::tuner::FrontendIsdbtTimeInterleaveMode; +using ::aidl::android::hardware::tv::tuner::FrontendIptvSettings; +using ::aidl::android::hardware::tv::tuner::FrontendIptvSettingsFec; +using ::aidl::android::hardware::tv::tuner::FrontendIptvSettingsProtocol; +using ::aidl::android::hardware::tv::tuner::FrontendIptvSettingsIgmp; +using ::aidl::android::hardware::tv::tuner::FrontendIptvSettingsFecType; using ::aidl::android::hardware::tv::tuner::FrontendModulation; using ::aidl::android::hardware::tv::tuner::FrontendModulationStatus; using ::aidl::android::hardware::tv::tuner::FrontendRollOff; @@ -3430,6 +3440,106 @@ static FrontendSettings getDtmbFrontendSettings(JNIEnv *env, const jobject &sett return frontendSettings; } +static DemuxIpAddress getDemuxIpAddress(JNIEnv *env, const jobject& config, const char* className) { + jclass clazz = env->FindClass(className); + + jbyteArray jsrcIpAddress = static_cast( + env->GetObjectField(config, env->GetFieldID(clazz, "mSrcIpAddress", "[B"))); + jsize srcSize = env->GetArrayLength(jsrcIpAddress); + jbyteArray jdstIpAddress = static_cast( + env->GetObjectField(config, env->GetFieldID(clazz, "mDstIpAddress", "[B"))); + jsize dstSize = env->GetArrayLength(jdstIpAddress); + + DemuxIpAddress res; + + if (srcSize != dstSize) { + // should never happen. Validated on Java size. + jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", + "IP address lengths don't match. srcLength=%d, dstLength=%d", srcSize, dstSize); + return res; + } + + if (srcSize == IP_V4_LENGTH) { + vector srcAddr; + vector dstAddr; + srcAddr.resize(IP_V4_LENGTH); + dstAddr.resize(IP_V4_LENGTH); + env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast(&srcAddr[0])); + env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast(&dstAddr[0])); + res.srcIpAddress.set(srcAddr); + res.dstIpAddress.set(dstAddr); + } else if (srcSize == IP_V6_LENGTH) { + vector srcAddr; + vector dstAddr; + srcAddr.resize(IP_V6_LENGTH); + dstAddr.resize(IP_V6_LENGTH); + env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast(&srcAddr[0])); + env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast(&dstAddr[0])); + res.srcIpAddress.set(srcAddr); + res.dstIpAddress.set(dstAddr); + } else { + // should never happen. Validated on Java size. + jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", + "Invalid IP address length %d", srcSize); + return res; + } + + res.srcPort = env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I")); + res.dstPort = env->GetIntField(config, env->GetFieldID(clazz, "mDstPort", "I")); + + return res; +} + +static FrontendIptvSettingsFec getIptvFrontendSettingsFec(JNIEnv *env, const jobject &settings) { + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/IptvFrontendSettings"); + jobject fec = env->GetObjectField(settings, env->GetFieldID(clazz, "mFec", + "[Landroid/media/tv/tuner/frontend/IptvFrontendSettingsFec;")); + jclass fecClazz = env->FindClass("android/media/tv/tuner/frontend/IptvFrontendSettingsFec"); + FrontendIptvSettingsFecType fecType = + static_cast( + env->GetIntField(fec, env->GetFieldID(fecClazz, "mFec", "I"))); + int32_t fecColNum = env->GetIntField(fec, env->GetFieldID(fecClazz, "mFecColNum", "I")); + int32_t fecRowNum = env->GetIntField(fec, env->GetFieldID(fecClazz, "mFecRowNum", "I")); + + FrontendIptvSettingsFec frontendIptvSettingsFec { + .type = fecType, + .fecColNum = fecColNum, + .fecRowNum = fecRowNum, + }; + + return frontendIptvSettingsFec; +} + +static FrontendSettings getIptvFrontendSettings(JNIEnv *env, const jobject &settings) { + FrontendSettings frontendSettings; + const char *clazzName = "android/media/tv/tuner/frontend/IptvFrontendSettings"; + jclass clazz = env->FindClass(clazzName); + FrontendIptvSettingsProtocol protocol = + static_cast( + env->GetIntField(settings, env->GetFieldID(clazz, "mProtocol", "I"))); + FrontendIptvSettingsIgmp igmp = + static_cast( + env->GetIntField(settings, env->GetFieldID(clazz, "mIgmp", "I"))); + FrontendIptvSettingsFec fec = getIptvFrontendSettingsFec(env, settings); + int64_t bitrate = env->GetIntField(settings, env->GetFieldID(clazz, "mBitrate", "J")); + jstring contentUrlJString = (jstring) env->GetObjectField(settings, env->GetFieldID( + clazz, "mContentUrl", + "[Landroid/media/tv/tuner/frontend/IptvFrontendSettings;")); + const char *contentUrl = env->GetStringUTFChars(contentUrlJString, 0); + DemuxIpAddress ipAddr = getDemuxIpAddress(env, settings, clazzName); + + FrontendIptvSettings frontendIptvSettings{ + .protocol = protocol, + .fec = fec, + .igmp = igmp, + .bitrate = bitrate, + .ipAddr = ipAddr, + .contentUrl = contentUrl, + }; + frontendSettings.set(frontendIptvSettings); + return frontendSettings; +} + static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) { ALOGV("getFrontendSettings %d", type); FrontendType feType = static_cast(type); @@ -3454,6 +3564,8 @@ static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject setti return getIsdbtFrontendSettings(env, settings); case FrontendType::DTMB: return getDtmbFrontendSettings(env, settings); + case FrontendType::IPTV: + return getIptvFrontendSettings(env, settings); default: // should never happen because a type is associated with a subclass of // FrontendSettings and not set by users @@ -3943,56 +4055,6 @@ static DemuxFilterDownloadSettings getFilterDownloadSettings(JNIEnv *env, const return filterDownloadSettings; } -static DemuxIpAddress getDemuxIpAddress(JNIEnv *env, const jobject& config) { - jclass clazz = env->FindClass("android/media/tv/tuner/filter/IpFilterConfiguration"); - - jbyteArray jsrcIpAddress = static_cast( - env->GetObjectField(config, env->GetFieldID(clazz, "mSrcIpAddress", "[B"))); - jsize srcSize = env->GetArrayLength(jsrcIpAddress); - jbyteArray jdstIpAddress = static_cast( - env->GetObjectField(config, env->GetFieldID(clazz, "mDstIpAddress", "[B"))); - jsize dstSize = env->GetArrayLength(jdstIpAddress); - - DemuxIpAddress res; - - if (srcSize != dstSize) { - // should never happen. Validated on Java size. - jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", - "IP address lengths don't match. srcLength=%d, dstLength=%d", srcSize, dstSize); - return res; - } - - if (srcSize == IP_V4_LENGTH) { - vector srcAddr; - vector dstAddr; - srcAddr.resize(IP_V4_LENGTH); - dstAddr.resize(IP_V4_LENGTH); - env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast(&srcAddr[0])); - env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast(&dstAddr[0])); - res.srcIpAddress.set(srcAddr); - res.dstIpAddress.set(dstAddr); - } else if (srcSize == IP_V6_LENGTH) { - vector srcAddr; - vector dstAddr; - srcAddr.resize(IP_V6_LENGTH); - dstAddr.resize(IP_V6_LENGTH); - env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast(&srcAddr[0])); - env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast(&dstAddr[0])); - res.srcIpAddress.set(srcAddr); - res.dstIpAddress.set(dstAddr); - } else { - // should never happen. Validated on Java size. - jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", - "Invalid IP address length %d", srcSize); - return res; - } - - res.srcPort = env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I")); - res.dstPort = env->GetIntField(config, env->GetFieldID(clazz, "mDstPort", "I")); - - return res; -} - static DemuxFilterSettings getFilterConfiguration( JNIEnv *env, int type, int subtype, jobject filterConfigObj) { DemuxFilterSettings filterSettings; @@ -4088,7 +4150,8 @@ static DemuxFilterSettings getFilterConfiguration( break; } case DemuxFilterMainType::IP: { - DemuxIpAddress ipAddr = getDemuxIpAddress(env, filterConfigObj); + DemuxIpAddress ipAddr = getDemuxIpAddress(env, filterConfigObj, + "android/media/tv/tuner/filter/IpFilterConfiguration"); DemuxIpFilterSettings ipFilterSettings { .ipAddr = ipAddr, };