From 87788c3118e0505a10556a269d6e92cd5d12f96a Mon Sep 17 00:00:00 2001 From: shubang Date: Tue, 4 Feb 2020 13:55:23 -0800 Subject: [PATCH] Parse FilterConfiguration in JNI Test: make; acloud create; Change-Id: I66d46e037a408c20a8b48c6363bcdfcb2d889ab9 --- media/java/android/media/tv/tuner/Tuner.java | 2 + .../android/media/tv/tuner/filter/Filter.java | 17 ++- .../tuner/filter/IpFilterConfiguration.java | 6 + media/jni/android_media_tv_Tuner.cpp | 138 +++++++++++++++--- 4 files changed, 144 insertions(+), 19 deletions(-) diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 9b183a3e0e920..44142e3249625 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -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(); diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java index 06de6e8a83c78..a98183bbf1a3d 100644 --- a/media/java/android/media/tv/tuner/filter/Filter.java +++ b/media/java/android/media/tv/tuner/filter/Filter.java @@ -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); } diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java index bf5aaeda4742e..a8dbfa5b11ecd 100644 --- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java +++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java @@ -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); } diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index 44f9b7c6eb39d..ac59003de5e6e 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -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( + 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) { + uint8_t srcAddr[IP_V4_LENGTH]; + uint8_t dstAddr[IP_V4_LENGTH]; + env->GetByteArrayRegion( + jsrcIpAddress, 0, srcSize, reinterpret_cast(srcAddr)); + env->GetByteArrayRegion( + jdstIpAddress, 0, dstSize, reinterpret_cast(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(srcAddr)); + env->GetByteArrayRegion( + jdstIpAddress, 0, dstSize, reinterpret_cast(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( + env->GetIntField(config, env->GetFieldID(clazz, "mSrcPort", "I"))); + uint16_t dstPort = static_cast( + 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( + env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mTpid", "I"))); DemuxTsFilterSettings tsFilterSettings { - .tpid = static_cast(tpid), + .tpid = tpid, }; DemuxTsFilterType tsType = static_cast(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( + env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mMmtpPid", "I"))); + DemuxMmtpFilterSettings mmtpFilterSettings { + .mmtpPid = mmtpPid, + }; DemuxMmtpFilterType mmtpType = static_cast(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(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( + 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( + env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I"))); + bool isCompressedIpPacket = static_cast( + env->GetBooleanField( + filterConfigObj, env->GetFieldID(clazz, "mIsCompressedIpPacket", "Z"))); + + DemuxTlvFilterSettings tlvFilterSettings { + .packetType = packetType, + .isCompressedIpPacket = isCompressedIpPacket, + }; DemuxTlvFilterType tlvType = static_cast(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( + 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( + env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mPacketType", "I"))); + DemuxAlpLengthType lengthType = static_cast( + env->GetIntField(filterConfigObj, env->GetFieldID(clazz, "mLengthType", "I"))); + DemuxAlpFilterSettings alpFilterSettings { + .packetType = packetType, + .lengthType = lengthType, + }; DemuxAlpFilterType alpType = static_cast(subtype); switch (alpType) { case DemuxAlpFilterType::SECTION: