Add filter class

Test: make; acloud
Change-Id: I4bdf2a7d952748d2c83d9d6e2c80f6104a8e472e
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index ebb1047..d1c171a 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -66,6 +66,8 @@
      */
     private native Frontend nativeOpenFrontendById(int id);
 
+    private native Filter nativeOpenFilter(int type, int subType, int bufferSize);
+
 
     /**
      * Frontend Callback.
@@ -99,4 +101,15 @@
         }
         return nativeOpenFrontendById(id);
     }
+
+    protected class Filter {
+        int mId;
+        private Filter(int id) {
+            mId = id;
+        }
+    }
+
+    private Filter openFilter(int type, int subType, int bufferSize) {
+        return nativeOpenFilter(type, subType, bufferSize);
+    }
 }
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index ba133fc..9e96b74 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -25,19 +25,34 @@
 
 #pragma GCC diagnostic ignored "-Wunused-function"
 
+using ::android::hardware::Void;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
 using ::android::hardware::tv::tuner::V1_0::ITuner;
 using ::android::hardware::tv::tuner::V1_0::Result;
 
 struct fields_t {
     jfieldID context;
     jmethodID frontendInitID;
+    jmethodID filterInitID;
 };
 
 static fields_t gFields;
 
 namespace android {
+/////////////// FilterCallback ///////////////////////
+//TODO: implement filter callback
+Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& /* filterEvent */) {
+    ALOGD("FilterCallback::onFilterEvent");
+    return Void();
+}
+Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus /*status*/) {
+    ALOGD("FilterCallback::onFilterStatu");
+    return Void();
+}
 
+/////////////// Tuner ///////////////////////
 sp<ITuner> JTuner::mTuner;
 
 JTuner::JTuner(JNIEnv *env, jobject thiz)
@@ -116,6 +131,54 @@
             (jint) jId);
 }
 
+bool JTuner::openDemux() {
+    if (mTuner == nullptr) {
+        return false;
+    }
+    if (mDemux != nullptr) {
+        return true;
+    }
+    mTuner->openDemux([&](Result, uint32_t demuxId, const sp<IDemux>& demux) {
+        mDemux = demux;
+        mDemuxId = demuxId;
+        ALOGD("open demux, id = %d", demuxId);
+    });
+    if (mDemux == nullptr) {
+        return false;
+    }
+    return true;
+}
+
+jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
+    if (mDemux == NULL) {
+        if (!openDemux()) {
+            return NULL;
+        }
+    }
+
+    sp<IFilter> f;
+    mDemux->openFilter(type, bufferSize, new FilterCallback,
+            [&](Result, const sp<IFilter>& filter) {
+                f = filter;
+            });
+    if (f == NULL) {
+        ALOGD("Failed to open filter, type = %d", type.mainType);
+        return NULL;
+    }
+    int fId;
+    f->getId([&](Result, uint32_t filterId) {
+        fId = filterId;
+    });
+    mFilters[fId] = f;
+
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    return env->NewObject(
+            env->FindClass("android/media/tv/tuner/Tuner$Filter"),
+            gFields.filterInitID,
+            mObject,
+            (jint) fId);
+}
+
 }  // namespace android
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -149,6 +212,10 @@
 
     jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend");
     gFields.frontendInitID = env->GetMethodID(frontendClazz, "<init>", "(I)V");
+
+    jclass filterClazz = env->FindClass("android/media/tv/tuner/Tuner$Filter");
+    gFields.filterInitID =
+            env->GetMethodID(filterClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
 }
 
 static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
@@ -166,6 +233,19 @@
     return tuner->openFrontendById(id);
 }
 
+static jobject android_media_tv_Tuner_open_filter(
+        JNIEnv *env, jobject thiz, jint type, jint subType, jint bufferSize) {
+    sp<JTuner> tuner = getTuner(env, thiz);
+    DemuxFilterType filterType {
+        .mainType = static_cast<DemuxFilterMainType>(type),
+    };
+
+    // TODO: other sub types
+    filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
+
+    return tuner->openFilter(filterType, bufferSize);
+}
+
 static const JNINativeMethod gMethods[] = {
     { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
     { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
@@ -173,6 +253,8 @@
             (void *)android_media_tv_Tuner_get_frontend_ids },
     { "nativeOpenFrontendById", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
             (void *)android_media_tv_Tuner_open_frontend_by_id },
+    { "nativeOpenFilter", "(III)Landroid/media/tv/tuner/Tuner$Filter;",
+            (void *)android_media_tv_Tuner_open_filter },
 };
 
 static int register_android_media_tv_Tuner(JNIEnv *env) {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 1425542..b23b394 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -18,22 +18,37 @@
 #define _ANDROID_MEDIA_TV_TUNER_H_
 
 #include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <unordered_map>
 #include <utils/RefBase.h>
 
 #include "jni.h"
 
+using ::android::hardware::Return;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
 using ::android::hardware::tv::tuner::V1_0::FrontendId;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IFilter;
+using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
 using ::android::hardware::tv::tuner::V1_0::IFrontend;
 using ::android::hardware::tv::tuner::V1_0::ITuner;
 
 namespace android {
 
+struct FilterCallback : public IFilterCallback {
+    virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
+    virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
+};
+
 struct JTuner : public RefBase {
     JTuner(JNIEnv *env, jobject thiz);
     sp<ITuner> getTunerService();
     jobject getFrontendIds();
     jobject openFrontendById(int id);
+    jobject openFilter(DemuxFilterType type, int bufferSize);
 protected:
+    bool openDemux();
     virtual ~JTuner();
 
 private:
@@ -41,6 +56,9 @@
     jweak mObject;
     static sp<ITuner> mTuner;
     sp<IFrontend> mFe;
+    sp<IDemux> mDemux;
+    int mDemuxId;
+    std::unordered_map<int, sp<IFilter>> mFilters;
 };
 
 }  // namespace android