Merge "Add JNI for IPTV"

This commit is contained in:
Hongguang Chen
2023-01-27 19:28:31 +00:00
committed by Android (Google) Code Review
2 changed files with 121 additions and 51 deletions

View File

@@ -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;

View File

@@ -132,6 +132,11 @@
#include <aidl/android/hardware/tv/tuner/FrontendIsdbtPartialReceptionFlag.h>
#include <aidl/android/hardware/tv/tuner/FrontendIsdbtSettings.h>
#include <aidl/android/hardware/tv/tuner/FrontendIsdbtTimeInterleaveMode.h>
#include <aidl/android/hardware/tv/tuner/FrontendIptvSettings.h>
#include <aidl/android/hardware/tv/tuner/FrontendIptvSettingsFec.h>
#include <aidl/android/hardware/tv/tuner/FrontendIptvSettingsProtocol.h>
#include <aidl/android/hardware/tv/tuner/FrontendIptvSettingsIgmp.h>
#include <aidl/android/hardware/tv/tuner/FrontendIptvSettingsFecType.h>
#include <aidl/android/hardware/tv/tuner/FrontendModulation.h>
#include <aidl/android/hardware/tv/tuner/FrontendModulationStatus.h>
#include <aidl/android/hardware/tv/tuner/FrontendRollOff.h>
@@ -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<jbyteArray>(
env->GetObjectField(config, env->GetFieldID(clazz, "mSrcIpAddress", "[B")));
jsize srcSize = env->GetArrayLength(jsrcIpAddress);
jbyteArray jdstIpAddress = static_cast<jbyteArray>(
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<uint8_t> srcAddr;
vector<uint8_t> dstAddr;
srcAddr.resize(IP_V4_LENGTH);
dstAddr.resize(IP_V4_LENGTH);
env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte *>(&srcAddr[0]));
env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte *>(&dstAddr[0]));
res.srcIpAddress.set<DemuxIpAddressIpAddress::Tag::v4>(srcAddr);
res.dstIpAddress.set<DemuxIpAddressIpAddress::Tag::v4>(dstAddr);
} else if (srcSize == IP_V6_LENGTH) {
vector<uint8_t> srcAddr;
vector<uint8_t> dstAddr;
srcAddr.resize(IP_V6_LENGTH);
dstAddr.resize(IP_V6_LENGTH);
env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte *>(&srcAddr[0]));
env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte *>(&dstAddr[0]));
res.srcIpAddress.set<DemuxIpAddressIpAddress::Tag::v6>(srcAddr);
res.dstIpAddress.set<DemuxIpAddressIpAddress::Tag::v6>(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<FrontendIptvSettingsFecType>(
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<FrontendIptvSettingsProtocol>(
env->GetIntField(settings, env->GetFieldID(clazz, "mProtocol", "I")));
FrontendIptvSettingsIgmp igmp =
static_cast<FrontendIptvSettingsIgmp>(
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<FrontendSettings::Tag::iptv>(frontendIptvSettings);
return frontendSettings;
}
static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
ALOGV("getFrontendSettings %d", type);
FrontendType feType = static_cast<FrontendType>(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<jbyteArray>(
env->GetObjectField(config, env->GetFieldID(clazz, "mSrcIpAddress", "[B")));
jsize srcSize = env->GetArrayLength(jsrcIpAddress);
jbyteArray jdstIpAddress = static_cast<jbyteArray>(
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<uint8_t> srcAddr;
vector<uint8_t> dstAddr;
srcAddr.resize(IP_V4_LENGTH);
dstAddr.resize(IP_V4_LENGTH);
env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte *>(&srcAddr[0]));
env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte *>(&dstAddr[0]));
res.srcIpAddress.set<DemuxIpAddressIpAddress::Tag::v4>(srcAddr);
res.dstIpAddress.set<DemuxIpAddressIpAddress::Tag::v4>(dstAddr);
} else if (srcSize == IP_V6_LENGTH) {
vector<uint8_t> srcAddr;
vector<uint8_t> dstAddr;
srcAddr.resize(IP_V6_LENGTH);
dstAddr.resize(IP_V6_LENGTH);
env->GetByteArrayRegion(jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte *>(&srcAddr[0]));
env->GetByteArrayRegion(jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte *>(&dstAddr[0]));
res.srcIpAddress.set<DemuxIpAddressIpAddress::Tag::v6>(srcAddr);
res.dstIpAddress.set<DemuxIpAddressIpAddress::Tag::v6>(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,
};