Merge "Parse FilterConfiguration in JNI"

This commit is contained in:
TreeHugger Robot
2020-02-13 23:14:20 +00:00
committed by Android (Google) Code Review
4 changed files with 144 additions and 19 deletions

View File

@@ -532,6 +532,8 @@ public class Tuner implements AutoCloseable {
Filter filter = nativeOpenFilter(
mainType, TunerUtils.getFilterSubtype(mainType, subType), bufferSize);
if (filter != null) {
filter.setMainType(mainType);
filter.setSubtype(subType);
filter.setCallback(cb);
if (mHandler == null) {
mHandler = createEventHandler();

View File

@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.tuner.TunerConstants.Result;
import android.media.tv.tuner.TunerUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -177,6 +178,8 @@ public class Filter implements AutoCloseable {
private long mNativeContext;
private FilterCallback mCallback;
private final int mId;
private int mMainType;
private int mSubtype;
private native int nativeConfigureFilter(
int type, int subType, FilterConfiguration settings);
@@ -196,6 +199,15 @@ public class Filter implements AutoCloseable {
private void onFilterStatus(int status) {
}
/** @hide */
public void setMainType(@Type int mainType) {
mMainType = mainType;
}
/** @hide */
public void setSubtype(@Subtype int subtype) {
mSubtype = subtype;
}
/** @hide */
public void setCallback(FilterCallback cb) {
mCallback = cb;
@@ -213,10 +225,13 @@ public class Filter implements AutoCloseable {
*/
@Result
public int configure(@NonNull FilterConfiguration config) {
int subType = -1;
// TODO: validate main type, subtype, config, settings
int subType;
Settings s = config.getSettings();
if (s != null) {
subType = s.getType();
} else {
subType = TunerUtils.getFilterSubtype(mMainType, mSubtype);
}
return nativeConfigureFilter(config.getType(), subType, config);
}

View File

@@ -160,6 +160,12 @@ public class IpFilterConfiguration extends FilterConfiguration {
*/
@NonNull
public IpFilterConfiguration build() {
int ipAddrLength = mSrcIpAddress.length;
if (ipAddrLength != mDstIpAddress.length || (ipAddrLength != 4 && ipAddrLength != 16)) {
throw new IllegalArgumentException(
"The lengths of src and dst IP address must be 4 or 16 and must be the same."
+ "srcLength=" + ipAddrLength + ", dstLength=" + mDstIpAddress.length);
}
return new IpFilterConfiguration(
mSettings, mSrcIpAddress, mDstIpAddress, mSrcPort, mDstPort, mPassthrough);
}

View File

@@ -32,6 +32,7 @@ using ::android::hardware::hidl_vec;
using ::android::hardware::tv::tuner::V1_0::DataFormat;
using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
using ::android::hardware::tv::tuner::V1_0::DemuxAlpLengthType;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterDownloadSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
@@ -40,6 +41,7 @@ using ::android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionBits;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxIpAddress;
using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterSettings;
@@ -129,6 +131,9 @@ struct fields_t {
static fields_t gFields;
static int IP_V4_LENGTH = 4;
static int IP_V6_LENGTH = 16;
namespace android {
/////////////// LnbCallback ///////////////////////
LnbCallback::LnbCallback(jweak tunerObj, LnbId id) : mObject(tunerObj), mId(id) {}
@@ -1509,12 +1514,67 @@ 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) {
uint8_t srcAddr[IP_V4_LENGTH];
uint8_t dstAddr[IP_V4_LENGTH];
env->GetByteArrayRegion(
jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr));
env->GetByteArrayRegion(
jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr));
res.srcIpAddress.v4(srcAddr);
res.dstIpAddress.v4(dstAddr);
} else if (srcSize == IP_V6_LENGTH) {
uint8_t srcAddr[IP_V6_LENGTH];
uint8_t dstAddr[IP_V6_LENGTH];
env->GetByteArrayRegion(
jsrcIpAddress, 0, srcSize, reinterpret_cast<jbyte*>(srcAddr));
env->GetByteArrayRegion(
jdstIpAddress, 0, dstSize, reinterpret_cast<jbyte*>(dstAddr));
res.srcIpAddress.v6(srcAddr);
res.dstIpAddress.v6(dstAddr);
} else {
// should never happen. Validated on Java size.
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"Invalid IP address length %d", srcSize);
return res;
}
uint16_t srcPort = static_cast<uint16_t>(
env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I")));
uint16_t dstPort = static_cast<uint16_t>(
env->GetIntField(config, env->GetFieldID(clazz, "mDstPort", "I")));
res.srcPort = srcPort;
res.dstPort = dstPort;
return res;
}
static DemuxFilterSettings getFilterConfiguration(
JNIEnv *env, int type, int subtype, jobject filterSettingsObj) {
JNIEnv *env, int type, int subtype, jobject filterConfigObj) {
DemuxFilterSettings filterSettings;
jobject settingsObj =
env->GetObjectField(
filterSettingsObj,
filterConfigObj,
env->GetFieldID(
env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"),
"mSettings",
@@ -1523,9 +1583,10 @@ static DemuxFilterSettings getFilterConfiguration(
switch (mainType) {
case DemuxFilterMainType::TS: {
jclass clazz = env->FindClass("android/media/tv/tuner/filter/TsFilterConfiguration");
int tpid = env->GetIntField(filterSettingsObj, env->GetFieldID(clazz, "mTpid", "I"));
uint16_t tpid = static_cast<uint16_t>(
env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mTpid", "I")));
DemuxTsFilterSettings tsFilterSettings {
.tpid = static_cast<uint16_t>(tpid),
.tpid = tpid,
};
DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype);
@@ -1553,7 +1614,12 @@ static DemuxFilterSettings getFilterConfiguration(
break;
}
case DemuxFilterMainType::MMTP: {
DemuxMmtpFilterSettings mmtpFilterSettings;
jclass clazz = env->FindClass("android/media/tv/tuner/filter/MmtpFilterConfiguration");
uint16_t mmtpPid = static_cast<uint16_t>(
env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mMmtpPid", "I")));
DemuxMmtpFilterSettings mmtpFilterSettings {
.mmtpPid = mmtpPid,
};
DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype);
switch (mmtpType) {
case DemuxMmtpFilterType::SECTION:
@@ -1583,43 +1649,79 @@ static DemuxFilterSettings getFilterConfiguration(
break;
}
case DemuxFilterMainType::IP: {
DemuxIpFilterSettings ipFilterSettings;
DemuxIpAddress ipAddr = getDemuxIpAddress(env, filterConfigObj);
DemuxIpFilterSettings ipFilterSettings {
.ipAddr = ipAddr,
};
DemuxIpFilterType ipType = static_cast<DemuxIpFilterType>(subtype);
switch (ipType) {
case DemuxIpFilterType::SECTION:
case DemuxIpFilterType::SECTION: {
ipFilterSettings.filterSettings.section(
getFilterSectionSettings(env, settingsObj));
break;
case DemuxIpFilterType::IP:
// TODO: handle passthrough
ipFilterSettings.filterSettings.bPassthrough(false);
}
case DemuxIpFilterType::IP: {
jclass clazz = env->FindClass(
"android/media/tv/tuner/filter/IpFilterConfiguration");
bool bPassthrough = static_cast<bool>(
env->GetBooleanField(
filterConfigObj, env->GetFieldID(
clazz, "mPassthrough", "Z")));
ipFilterSettings.filterSettings.bPassthrough(bPassthrough);
break;
default:
}
default: {
break;
}
}
filterSettings.ip(ipFilterSettings);
break;
}
case DemuxFilterMainType::TLV: {
DemuxTlvFilterSettings tlvFilterSettings;
jclass clazz = env->FindClass("android/media/tv/tuner/filter/TlvFilterConfiguration");
uint8_t packetType = static_cast<uint8_t>(
env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I")));
bool isCompressedIpPacket = static_cast<bool>(
env->GetBooleanField(
filterConfigObj, env->GetFieldID(clazz, "mIsCompressedIpPacket", "Z")));
DemuxTlvFilterSettings tlvFilterSettings {
.packetType = packetType,
.isCompressedIpPacket = isCompressedIpPacket,
};
DemuxTlvFilterType tlvType = static_cast<DemuxTlvFilterType>(subtype);
switch (tlvType) {
case DemuxTlvFilterType::SECTION:
case DemuxTlvFilterType::SECTION: {
tlvFilterSettings.filterSettings.section(
getFilterSectionSettings(env, settingsObj));
break;
case DemuxTlvFilterType::TLV:
// TODO: handle passthrough
tlvFilterSettings.filterSettings.bPassthrough(false);
}
case DemuxTlvFilterType::TLV: {
bool bPassthrough = static_cast<bool>(
env->GetBooleanField(
filterConfigObj, env->GetFieldID(
clazz, "mPassthrough", "Z")));
tlvFilterSettings.filterSettings.bPassthrough(bPassthrough);
break;
default:
}
default: {
break;
}
}
filterSettings.tlv(tlvFilterSettings);
break;
}
case DemuxFilterMainType::ALP: {
DemuxAlpFilterSettings alpFilterSettings;
jclass clazz = env->FindClass("android/media/tv/tuner/filter/AlpFilterConfiguration");
uint8_t packetType = static_cast<uint8_t>(
env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I")));
DemuxAlpLengthType lengthType = static_cast<DemuxAlpLengthType>(
env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mLengthType", "I")));
DemuxAlpFilterSettings alpFilterSettings {
.packetType = packetType,
.lengthType = lengthType,
};
DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype);
switch (alpType) {
case DemuxAlpFilterType::SECTION: