Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 87788c31 authored by shubang's avatar shubang Committed by Shubang Lu
Browse files

Parse FilterConfiguration in JNI

Test: make; acloud create;
Change-Id: I66d46e037a408c20a8b48c6363bcdfcb2d889ab9
parent 44fa142e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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();
+16 −1
Original line number Diff line number Diff line
@@ -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);
    }
+6 −0
Original line number Diff line number Diff line
@@ -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);
        }
+120 −18
Original line number Diff line number Diff line
@@ -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: