Filter settings and configure()

Test: make; acloud;
Change-Id: Idf5774b1b7d6fbd2e512c55abf5618ce26cc7965
diff --git a/media/java/android/media/tv/tuner/FilterSettings.java b/media/java/android/media/tv/tuner/FilterSettings.java
new file mode 100644
index 0000000..d5f1003
--- /dev/null
+++ b/media/java/android/media/tv/tuner/FilterSettings.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.annotation.Nullable;
+import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.TunerConstants.FilterSettingsType;
+
+import java.util.List;
+
+/**
+ * Demux Filter settings.
+ *
+ * @hide
+ */
+public abstract class FilterSettings {
+    @Nullable
+    protected final Settings mSettings;
+
+    protected FilterSettings(Settings settings) {
+        mSettings = settings;
+    }
+
+    /**
+     * Gets filter settings type
+     */
+    @FilterSettingsType public abstract int getType();
+
+    // TODO: more builders and getters
+
+    /**
+     *  Filter Settings for a TS filter.
+     */
+    public static class TsFilterSettings extends FilterSettings {
+        private int mTpid;
+
+        private TsFilterSettings(Settings settings, int tpid) {
+            super(settings);
+            mTpid = tpid;
+        }
+
+        @Override
+        public int getType() {
+            return TunerConstants.FILTER_SETTINGS_TS;
+        }
+
+        /**
+         * Creates a new builder.
+         */
+        public static Builder newBuilder() {
+            return new Builder();
+        }
+
+        /**
+         * Builder for TsFilterSettings.
+         */
+        public static class Builder {
+            private Settings mSettings;
+            private int mTpid;
+
+            /**
+             * Sets settings.
+             */
+            public Builder setSettings(Settings settings) {
+                mSettings = settings;
+                return this;
+            }
+
+            /**
+             * Sets TPID.
+             */
+            public Builder setTpid(int tpid) {
+                mTpid = tpid;
+                return this;
+            }
+
+            /**
+             * Builds a TsFilterSettings instance.
+             */
+            public TsFilterSettings build() {
+                return new TsFilterSettings(mSettings, mTpid);
+            }
+        }
+    }
+
+    /**
+     *  Filter Settings for a MMTP filter.
+     */
+    public static class MmtpFilterSettings extends FilterSettings {
+        private int mMmtpPid;
+
+        public MmtpFilterSettings(Settings settings) {
+            super(settings);
+        }
+
+        @Override
+        public int getType() {
+            return TunerConstants.FILTER_SETTINGS_MMTP;
+        }
+    }
+
+
+    /**
+     *  Filter Settings for a IP filter.
+     */
+    public static class IpFilterSettings extends FilterSettings {
+        private byte[] mSrcIpAddress;
+        private byte[] mDstIpAddress;
+        private int mSrcPort;
+        private int mDstPort;
+        private boolean mPassthrough;
+
+        public IpFilterSettings(Settings settings) {
+            super(settings);
+        }
+
+        @Override
+        public int getType() {
+            return TunerConstants.FILTER_SETTINGS_IP;
+        }
+    }
+
+
+    /**
+     *  Filter Settings for a TLV filter.
+     */
+    public static class TlvFilterSettings extends FilterSettings {
+        private int mPacketType;
+        private boolean mIsCompressedIpPacket;
+        private boolean mPassthrough;
+
+        public TlvFilterSettings(Settings settings) {
+            super(settings);
+        }
+
+        @Override
+        public int getType() {
+            return TunerConstants.FILTER_SETTINGS_TLV;
+        }
+    }
+
+
+    /**
+     *  Filter Settings for a ALP filter.
+     */
+    public static class AlpFilterSettings extends FilterSettings {
+        private int mPacketType;
+        private int mLengthType;
+
+        public AlpFilterSettings(Settings settings) {
+            super(settings);
+        }
+
+        @Override
+        public int getType() {
+            return TunerConstants.FILTER_SETTINGS_ALP;
+        }
+    }
+
+
+    /**
+     *  Settings for filters of different subtypes.
+     */
+    public abstract static class Settings {
+        protected final int mType;
+
+        protected Settings(int type) {
+            mType = type;
+        }
+
+        /**
+         * Gets filter settings type.
+         * @return
+         */
+        int getType() {
+            return mType;
+        }
+    }
+
+    /**
+     *  Filter Settings for Section data according to ISO/IEC 13818-1.
+     */
+    public static class SectionSettings extends Settings {
+
+        private SectionSettings(int mainType) {
+            super(SectionSettings.findType(mainType));
+        }
+
+        private static int findType(int mainType) {
+            switch (mainType) {
+                case TunerConstants.FILTER_SETTINGS_TS:
+                    return Constants.DemuxTsFilterType.SECTION;
+                case TunerConstants.FILTER_SETTINGS_MMTP:
+                    return Constants.DemuxMmtpFilterType.SECTION;
+                case TunerConstants.FILTER_SETTINGS_IP:
+                    return Constants.DemuxIpFilterType.SECTION;
+                case TunerConstants.FILTER_SETTINGS_TLV:
+                    return Constants.DemuxTlvFilterType.SECTION;
+                case TunerConstants.FILTER_SETTINGS_ALP:
+                    return Constants.DemuxAlpFilterType.SECTION;
+            }
+            // UNDEFINED
+            return 0;
+        }
+    }
+
+    /**
+     *  Bits Settings for Section Filter.
+     */
+    public static class SectionSettingsWithSectionBits extends SectionSettings {
+        private List<Byte> mFilter;
+        private List<Byte> mMask;
+        private List<Byte> mMode;
+
+        private SectionSettingsWithSectionBits(int mainType) {
+            super(mainType);
+        }
+    }
+
+    /**
+     *  Table information for Section Filter.
+     */
+    public static class SectionSettingsWithTableInfo extends SectionSettings {
+        private int mTableId;
+        private int mVersion;
+
+        private SectionSettingsWithTableInfo(int mainType) {
+            super(mainType);
+        }
+    }
+
+    /**
+     *  Filter Settings for a PES Data.
+     */
+    public static class PesSettings extends Settings {
+        private int mStreamId;
+        private boolean mIsRaw;
+
+        private PesSettings(int mainType, int streamId, boolean isRaw) {
+            super(PesSettings.findType(mainType));
+            mStreamId = streamId;
+            mIsRaw = isRaw;
+        }
+
+        private static int findType(int mainType) {
+            switch (mainType) {
+                case TunerConstants.FILTER_SETTINGS_TS:
+                    return Constants.DemuxTsFilterType.PES;
+                case TunerConstants.FILTER_SETTINGS_MMTP:
+                    return Constants.DemuxMmtpFilterType.PES;
+            }
+            // UNDEFINED
+            return 0;
+        }
+
+        /**
+         * Creates a builder for PesSettings.
+         */
+        public static Builder newBuilder(int mainType) {
+            return new Builder(mainType);
+        }
+
+        /**
+         * Builder for PesSettings.
+         */
+        public static class Builder {
+            private final int mMainType;
+            private int mStreamId;
+            private boolean mIsRaw;
+
+            public Builder(int mainType) {
+                mMainType = mainType;
+            }
+
+            /**
+             * Sets stream ID.
+             */
+            public Builder setStreamId(int streamId) {
+                mStreamId = streamId;
+                return this;
+            }
+
+            /**
+             * Sets whether it's raw.
+             * true if the filter send onFilterStatus instead of onFilterEvent.
+             */
+            public Builder setIsRaw(boolean isRaw) {
+                mIsRaw = isRaw;
+                return this;
+            }
+
+            /**
+             * Builds a PesSettings instance.
+             */
+            public PesSettings build() {
+                return new PesSettings(mMainType, mStreamId, mIsRaw);
+            }
+        }
+    }
+
+    /**
+     *  Filter Settings for a Video and Audio.
+     */
+    public static class AvSettings extends Settings {
+        private boolean mIsPassthrough;
+
+        private AvSettings(int mainType, boolean isAudio) {
+            super(AvSettings.findType(mainType, isAudio));
+        }
+
+        private static int findType(int mainType, boolean isAudio) {
+            switch (mainType) {
+                case TunerConstants.FILTER_SETTINGS_TS:
+                    return isAudio
+                            ? Constants.DemuxTsFilterType.AUDIO
+                            : Constants.DemuxTsFilterType.VIDEO;
+                case TunerConstants.FILTER_SETTINGS_MMTP:
+                    return isAudio
+                            ? Constants.DemuxMmtpFilterType.AUDIO
+                            : Constants.DemuxMmtpFilterType.VIDEO;
+            }
+            // UNDEFINED
+            return 0;
+        }
+    }
+
+    /**
+     *  Filter Settings for a Download.
+     */
+    public static class DownloadSettings extends Settings {
+        private int mDownloadId;
+
+        public DownloadSettings(int mainType) {
+            super(DownloadSettings.findType(mainType));
+        }
+
+        private static int findType(int mainType) {
+            if (mainType == TunerConstants.FILTER_SETTINGS_MMTP) {
+                return Constants.DemuxMmtpFilterType.DOWNLOAD;
+            }
+            // UNDEFINED
+            return 0;
+        }
+    }
+
+    /**
+     *  The Settings for the record in DVR.
+     */
+    public static class RecordSettings extends Settings {
+        private int mIndexType;
+        private int mIndexMask;
+
+        public RecordSettings(int mainType) {
+            super(RecordSettings.findType(mainType));
+        }
+
+        private static int findType(int mainType) {
+            switch (mainType) {
+                case TunerConstants.FILTER_SETTINGS_TS:
+                    return Constants.DemuxTsFilterType.RECORD;
+                case TunerConstants.FILTER_SETTINGS_MMTP:
+                    return Constants.DemuxMmtpFilterType.RECORD;
+            }
+            // UNDEFINED
+            return 0;
+        }
+    }
+
+}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 82cef2e..54ad456 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -243,6 +243,7 @@
         private FilterCallback mCallback;
         int mId;
 
+        private native int nativeConfigureFilter(int type, int subType, FilterSettings settings);
         private native boolean nativeStartFilter();
         private native boolean nativeStopFilter();
         private native boolean nativeFlushFilter();
@@ -258,6 +259,14 @@
             }
         }
 
+        public int configure(FilterSettings settings) {
+            int subType = -1;
+            if (settings.mSettings != null) {
+                subType = settings.mSettings.getType();
+            }
+            return nativeConfigureFilter(settings.getType(), subType, settings);
+        }
+
         public boolean start() {
             return nativeStartFilter();
         }
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index 458cb16..f2d5e93 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -90,6 +90,17 @@
     public static final int FRONTEND_SETTINGS_ISDBS3 = 8;
     public static final int FRONTEND_SETTINGS_ISDBT = 9;
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({FILTER_SETTINGS_TS, FILTER_SETTINGS_MMTP, FILTER_SETTINGS_IP, FILTER_SETTINGS_TLV,
+            FILTER_SETTINGS_ALP})
+    public @interface FilterSettingsType {}
+
+    public static final int FILTER_SETTINGS_TS = Constants.DemuxFilterMainType.TS;
+    public static final int FILTER_SETTINGS_MMTP = Constants.DemuxFilterMainType.MMTP;
+    public static final int FILTER_SETTINGS_IP = Constants.DemuxFilterMainType.IP;
+    public static final int FILTER_SETTINGS_TLV = Constants.DemuxFilterMainType.TLV;
+    public static final int FILTER_SETTINGS_ALP = Constants.DemuxFilterMainType.ALP;
+
     private TunerConstants() {
     }
 }
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 5216906..8bc6efc 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -28,8 +28,11 @@
 using ::android::hardware::Void;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
 using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid;
 using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
 using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings;
 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
@@ -542,6 +545,56 @@
     return tuner->openFilter(filterType, bufferSize);
 }
 
+static DemuxFilterSettings getFilterSettings(
+        JNIEnv *env, int type, int subtype, jobject filterSettingsObj) {
+    DemuxFilterSettings filterSettings;
+    // TODO: more setting types
+    jobject settingsObj =
+            env->GetObjectField(
+                    filterSettingsObj,
+                    env->GetFieldID(
+                            env->FindClass("android/media/tv/tuner/FilterSettings"),
+                            "mSettings",
+                            "Landroid/media/tv/tuner/FilterSettings$Settings;"));
+    if (type == (int)DemuxFilterMainType::TS) {
+        // DemuxTsFilterSettings
+        jclass clazz = env->FindClass("android/media/tv/tuner/FilterSettings$TsFilterSettings");
+        int tpid = env->GetIntField(filterSettingsObj, env->GetFieldID(clazz, "mTpid", "I"));
+        if (subtype == (int)DemuxTsFilterType::PES) {
+            // DemuxFilterPesDataSettings
+            jclass settingClazz =
+                    env->FindClass("android/media/tv/tuner/FilterSettings$PesSettings");
+            int streamId = env->GetIntField(
+                    settingsObj, env->GetFieldID(settingClazz, "mStreamId", "I"));
+            bool isRaw = (bool)env->GetBooleanField(
+                    settingsObj, env->GetFieldID(settingClazz, "mIsRaw", "Z"));
+            DemuxFilterPesDataSettings filterPesDataSettings {
+                    .streamId = static_cast<uint16_t>(streamId),
+                    .isRaw = isRaw,
+            };
+            DemuxTsFilterSettings tsFilterSettings {
+                    .tpid = static_cast<uint16_t>(tpid),
+            };
+            tsFilterSettings.filterSettings.pesData(filterPesDataSettings);
+            filterSettings.ts(tsFilterSettings);
+        }
+    }
+    return filterSettings;
+}
+
+static int android_media_tv_Tuner_configure_filter(
+        JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
+    ALOGD("configure filter type=%d, subtype=%d", type, subtype);
+    sp<IFilter> filterSp = getFilter(env, filter);
+    if (filterSp == NULL) {
+        ALOGD("Failed to configure filter: filter not found");
+        return (int)Result::INVALID_STATE;
+    }
+    DemuxFilterSettings filterSettings = getFilterSettings(env, type, subtype, settings);
+    Result res = filterSp->configure(filterSettings);
+    return (int)res;
+}
+
 static bool android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
     sp<IFilter> filterSp = getFilter(env, filter);
     if (filterSp == NULL) {
@@ -670,6 +723,8 @@
 };
 
 static const JNINativeMethod gFilterMethods[] = {
+    { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/FilterSettings;)I",
+            (void *)android_media_tv_Tuner_configure_filter },
     { "nativeStartFilter", "()Z", (void *)android_media_tv_Tuner_start_filter },
     { "nativeStopFilter", "()Z", (void *)android_media_tv_Tuner_stop_filter },
     { "nativeFlushFilter", "()Z", (void *)android_media_tv_Tuner_flush_filter },