TunerService: create TunerFilter and TunerDemux

Bug: 177529575
Bug: 177530961
Test: make
Change-Id: I228d6b1fe5a3e6552fda4290a37f036eeee1d85a
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index 1379090..6a21b0e 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -64,7 +64,7 @@
     name: "libtunerservice",
 
     srcs: [
-        "Tuner*.cpp"
+        "Tuner*.cpp",
     ],
 
     shared_libs: [
@@ -86,7 +86,7 @@
     ],
 
     include_dirs: [
-      "frameworks/av/include"
+        "frameworks/av/include"
     ],
 
     cflags: [
diff --git a/services/tuner/TunerDemux.cpp b/services/tuner/TunerDemux.cpp
new file mode 100644
index 0000000..edd1802
--- /dev/null
+++ b/services/tuner/TunerDemux.cpp
@@ -0,0 +1,103 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#define LOG_TAG "TunerDemux"
+
+#include "TunerDemux.h"
+#include "TunerFilter.h"
+
+using ::android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+namespace android {
+
+TunerDemux::TunerDemux(sp<IDemux> demux, int id) {
+    mDemux = demux;
+    mDemuxId = id;
+}
+
+TunerDemux::~TunerDemux() {
+    mDemux = nullptr;
+}
+
+Status TunerDemux::setFrontendDataSource(const std::shared_ptr<ITunerFrontend>& frontend) {
+    if (mDemux == nullptr) {
+        ALOGE("IDemux is not initialized");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    int frontendId;
+    frontend->getFrontendId(&frontendId);
+    Result res = mDemux->setFrontendDataSource(frontendId);
+    if (res != Result::SUCCESS) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+    }
+    return Status::ok();
+}
+
+Status TunerDemux::openFilter(
+        int type, int subType, int bufferSize, const std::shared_ptr<ITunerFilterCallback>& cb,
+        std::shared_ptr<ITunerFilter>* _aidl_return) {
+    if (mDemux == nullptr) {
+        ALOGE("IDemux is not initialized.");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type);
+    DemuxFilterType filterType {
+        .mainType = mainType,
+    };
+
+    switch(mainType) {
+        case DemuxFilterMainType::TS:
+            filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
+            break;
+        case DemuxFilterMainType::MMTP:
+            filterType.subType.mmtpFilterType(static_cast<DemuxMmtpFilterType>(subType));
+            break;
+        case DemuxFilterMainType::IP:
+            filterType.subType.ipFilterType(static_cast<DemuxIpFilterType>(subType));
+            break;
+        case DemuxFilterMainType::TLV:
+            filterType.subType.tlvFilterType(static_cast<DemuxTlvFilterType>(subType));
+            break;
+        case DemuxFilterMainType::ALP:
+            filterType.subType.alpFilterType(static_cast<DemuxAlpFilterType>(subType));
+            break;
+    }
+    Result status;
+    sp<IFilter> filterSp;
+    sp<IFilterCallback> cbSp = new TunerFilter::FilterCallback(cb);
+    mDemux->openFilter(filterType, bufferSize, cbSp,
+            [&](Result r, const sp<IFilter>& filter) {
+                filterSp = filter;
+                status = r;
+            });
+    if (status != Result::SUCCESS) {
+        return Status::fromServiceSpecificError(static_cast<int32_t>(status));
+    }
+
+    *_aidl_return = ::ndk::SharedRefBase::make<TunerFilter>(filterSp, cbSp);
+    return Status::ok();
+}
+
+}  // namespace android
diff --git a/services/tuner/TunerDemux.h b/services/tuner/TunerDemux.h
new file mode 100644
index 0000000..6eca8ab
--- /dev/null
+++ b/services/tuner/TunerDemux.h
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#ifndef ANDROID_MEDIA_TUNERDEMUX_H
+#define ANDROID_MEDIA_TUNERDEMUX_H
+
+#include <aidl/android/media/tv/tuner/BnTunerDemux.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+
+using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::media::tv::tuner::BnTunerDemux;
+using ::aidl::android::media::tv::tuner::ITunerFilter;
+using ::aidl::android::media::tv::tuner::ITunerFilterCallback;
+using ::aidl::android::media::tv::tuner::ITunerFrontend;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+
+
+namespace android {
+
+class TunerDemux : public BnTunerDemux {
+
+public:
+    TunerDemux(sp<IDemux> demux, int demuxId);
+    virtual ~TunerDemux();
+    Status setFrontendDataSource(const std::shared_ptr<ITunerFrontend>& frontend) override;
+    Status openFilter(
+        int mainType, int subtype, int bufferSize, const std::shared_ptr<ITunerFilterCallback>& cb,
+        std::shared_ptr<ITunerFilter>* _aidl_return);
+
+private:
+    sp<IDemux> mDemux;
+    int mDemuxId;
+};
+
+} // namespace android
+
+#endif // ANDROID_MEDIA_TUNERDEMUX_H
diff --git a/services/tuner/TunerFilter.cpp b/services/tuner/TunerFilter.cpp
new file mode 100644
index 0000000..5a2f404
--- /dev/null
+++ b/services/tuner/TunerFilter.cpp
@@ -0,0 +1,64 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#define LOG_TAG "TunerFilter"
+
+#include "TunerFilter.h"
+
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+namespace android {
+
+TunerFilter::TunerFilter(sp<IFilter> filter, sp<IFilterCallback> callback) {
+    mFilter = filter;
+    mFilterCallback = callback;
+}
+
+TunerFilter::~TunerFilter() {
+    mFilter = nullptr;
+    mFilterCallback = nullptr;
+}
+
+Status TunerFilter::getId(int32_t* _aidl_return) {
+    if (mFilter == nullptr) {
+        ALOGE("IFilter is not initialized");
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::UNAVAILABLE));
+    }
+
+    Result res;
+    mFilter->getId([&](Result r, uint32_t filterId) {
+        res = r;
+        mId = filterId;
+    });
+    if (res != Result::SUCCESS) {
+        return ::ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(res));
+    }
+    *_aidl_return = mId;
+    return Status::ok();
+}
+
+/////////////// FilterCallback ///////////////////////
+
+Return<void> TunerFilter::FilterCallback::onFilterStatus(DemuxFilterStatus status) {
+    mTunerFilterCallback->onFilterStatus((int)status);
+    return Void();
+}
+
+Return<void> TunerFilter::FilterCallback::onFilterEvent(const DemuxFilterEvent&) {
+    return Void();
+}
+
+}  // namespace android
diff --git a/services/tuner/TunerFilter.h b/services/tuner/TunerFilter.h
new file mode 100644
index 0000000..54c618e
--- /dev/null
+++ b/services/tuner/TunerFilter.h
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2021, 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.
+ */
+
+#ifndef ANDROID_MEDIA_TUNERFILTER_H
+#define ANDROID_MEDIA_TUNERFILTER_H
+
+#include <aidl/android/media/tv/tuner/BnTunerFilter.h>
+#include <aidl/android/media/tv/tuner/ITunerFilterCallback.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+using Status = ::ndk::ScopedAStatus;
+using ::aidl::android::media::tv::tuner::BnTunerFilter;
+using ::aidl::android::media::tv::tuner::ITunerFilterCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using ::android::hardware::tv::tuner::V1_0::IFilter;
+using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
+
+
+namespace android {
+
+class TunerFilter : public BnTunerFilter {
+
+public:
+    TunerFilter(sp<IFilter> filter, sp<IFilterCallback> callback);
+    virtual ~TunerFilter();
+    Status getId(int32_t* _aidl_return) override;
+
+    struct FilterCallback : public IFilterCallback {
+        FilterCallback(const std::shared_ptr<ITunerFilterCallback> tunerFilterCallback)
+                : mTunerFilterCallback(tunerFilterCallback) {};
+
+        virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
+        virtual Return<void> onFilterStatus(DemuxFilterStatus status);
+
+        std::shared_ptr<ITunerFilterCallback> mTunerFilterCallback;
+    };
+
+private:
+    sp<IFilter> mFilter;
+    sp<IFilterCallback> mFilterCallback;
+    int32_t mId;
+};
+
+} // namespace android
+
+#endif // ANDROID_MEDIA_TUNERFILTER_H
diff --git a/services/tuner/TunerService.cpp b/services/tuner/TunerService.cpp
index ef3d1f2..f97cbfe 100644
--- a/services/tuner/TunerService.cpp
+++ b/services/tuner/TunerService.cpp
@@ -21,6 +21,7 @@
 #include "TunerService.h"
 #include "TunerFrontend.h"
 #include "TunerLnb.h"
+#include "TunerDemux.h"
 
 using ::aidl::android::media::tv::tuner::TunerFrontendAnalogCapabilities;
 using ::aidl::android::media::tv::tuner::TunerFrontendAtsc3Capabilities;
@@ -113,17 +114,19 @@
     return true;
 }
 
-Result TunerService::openDemux() {
+Status TunerService::openDemux(
+        int /* demuxHandle */, std::shared_ptr<ITunerDemux>* _aidl_return) {
     ALOGD("openDemux");
     if (!getITuner()) {
-        return Result::NOT_INITIALIZED;
+        return Status::fromServiceSpecificError(static_cast<int32_t>(Result::NOT_INITIALIZED));
     }
     if (mDemux != nullptr) {
-        return Result::SUCCESS;
+        *_aidl_return = mDemux->ref<ITunerDemux>();
+        return Status::ok();
     }
     Result res;
     uint32_t id;
-    sp<IDemux> demuxSp;
+    sp<IDemux> demuxSp = nullptr;
     mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
         demuxSp = demux;
         id = demuxId;
@@ -131,37 +134,14 @@
         ALOGD("open demux, id = %d", demuxId);
     });
     if (res == Result::SUCCESS) {
-        mDemux = demuxSp;
-    } else {
-        ALOGD("open demux failed, res = %d", res);
-    }
-    return res;
-}
-
-Result TunerService::openFilter() {
-    ALOGD("openFilter");
-    if (!getITuner()) {
-        return Result::NOT_INITIALIZED;
-    }
-    DemuxFilterMainType mainType = DemuxFilterMainType::TS;
-    DemuxFilterType filterType {
-        .mainType = mainType,
-    };
-    filterType.subType.tsFilterType(DemuxTsFilterType::VIDEO);
-
-    sp<FilterCallback> callback = new FilterCallback();
-    Result res;
-    mDemux->openFilter(filterType, 16000000, callback,
-            [&](Result r, const sp<IFilter>& filter) {
-                mFilter = filter;
-                res = r;
-            });
-    if (res != Result::SUCCESS || mFilter == NULL) {
-        ALOGD("Failed to open filter, type = %d", filterType.mainType);
-        return res;
+        mDemux = ::ndk::SharedRefBase::make<TunerDemux>(demuxSp, id);
+        *_aidl_return = mDemux->ref<ITunerDemux>();
+        return Status::ok();
     }
 
-    return Result::SUCCESS;
+    ALOGD("open demux failed, res = %d", res);
+    mDemux = nullptr;
+    return Status::fromServiceSpecificError(static_cast<int32_t>(res));
 }
 
 Result TunerService::configFilter() {
@@ -273,8 +253,6 @@
         MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) {
     ALOGD("getFmqSyncReadWrite");
     // TODO: put the following methods AIDL, and should be called from clients.
-    openDemux();
-    openFilter();
     configFilter();
     mFilter->start();
     if (mqDesc == nullptr) {
diff --git a/services/tuner/TunerService.h b/services/tuner/TunerService.h
index 82b6fcd..197e4f3 100644
--- a/services/tuner/TunerService.h
+++ b/services/tuner/TunerService.h
@@ -27,6 +27,7 @@
 using ::aidl::android::hardware::common::fmq::MQDescriptor;
 using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
 using ::aidl::android::media::tv::tuner::BnTunerService;
+using ::aidl::android::media::tv::tuner::ITunerDemux;
 using ::aidl::android::media::tv::tuner::ITunerFrontend;
 using ::aidl::android::media::tv::tuner::ITunerLnb;
 using ::aidl::android::media::tv::tuner::TunerFrontendInfo;
@@ -101,6 +102,7 @@
             MQDescriptor<int8_t, SynchronizedReadWrite>* mqDesc, bool* _aidl_return) override;
     Status openLnb(int lnbHandle, shared_ptr<ITunerLnb>* _aidl_return) override;
     Status openLnbByName(const string& lnbName, shared_ptr<ITunerLnb>* _aidl_return) override;
+    Status openDemux(int32_t demuxHandle, std::shared_ptr<ITunerDemux>* _aidl_return) override;
 
 private:
     template <typename HidlPayload, typename AidlPayload, typename AidlFlavor>
@@ -109,12 +111,10 @@
             MQDescriptor<AidlPayload, AidlFlavor>* aidl);
 
     bool getITuner();
-    Result openFilter();
-    Result openDemux();
     Result configFilter();
 
     sp<ITuner> mTuner;
-    sp<IDemux> mDemux;
+    std::shared_ptr<ITunerDemux> mDemux;
     sp<IFilter> mFilter;
     AidlMessageQueue* mAidlMq;
     MQDescriptorSync<uint8_t> mFilterMQDesc;
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerDemux.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerDemux.aidl
new file mode 100644
index 0000000..0e4e99c
--- /dev/null
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerDemux.aidl
@@ -0,0 +1,40 @@
+/**
+ * Copyright 2021, 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.media.tv.tuner.ITunerFilter;
+import android.media.tv.tuner.ITunerFilterCallback;
+import android.media.tv.tuner.ITunerFrontend;
+
+/**
+ * Tuner Demux interface handles tuner related operations.
+ *
+ * {@hide}
+ */
+interface ITunerDemux {
+
+    /**
+     * Set a frontend resource as data input of the demux
+     */
+    void setFrontendDataSource(in ITunerFrontend frontend);
+
+    /**
+     * Open a new filter in the demux
+     */
+    ITunerFilter openFilter(
+        in int mainType, in int subtype, in int bufferSize, in ITunerFilterCallback cb);
+}
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl
new file mode 100644
index 0000000..24c6289
--- /dev/null
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerFilter.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2021, 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;
+
+/**
+ * Tuner Filter interface handles tuner related operations.
+ *
+ * {@hide}
+ */
+interface ITunerFilter {
+    /**
+     * Get the filter Id.
+     */
+    int getId();
+}
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerFilterCallback.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerFilterCallback.aidl
new file mode 100644
index 0000000..2733d3c
--- /dev/null
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerFilterCallback.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2021, 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;
+
+/**
+ * TunerFilterCallback interface handles tuner filter related callbacks.
+ *
+ * {@hide}
+ */
+interface ITunerFilterCallback {
+    /**
+     * Notify the client a new status of a filter.
+     */
+    void onFilterStatus(int status);
+}
diff --git a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
index 5b60685..ac6eaab 100644
--- a/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
+++ b/services/tuner/aidl/android/media/tv/tuner/ITunerService.aidl
@@ -19,6 +19,7 @@
 import android.hardware.common.fmq.MQDescriptor;
 import android.hardware.common.fmq.SynchronizedReadWrite;
 import android.hardware.common.fmq.UnsynchronizedWrite;
+import android.media.tv.tuner.ITunerDemux;
 import android.media.tv.tuner.ITunerFrontend;
 import android.media.tv.tuner.ITunerLnb;
 import android.media.tv.tuner.TunerFrontendInfo;
@@ -77,4 +78,8 @@
      */
     ITunerLnb openLnbByName(in String lnbName);
 
+    /**
+     * Create a new instance of Demux.
+     */
+    ITunerDemux openDemux(in int demuxHandle);
 }