Refactor JNI to remove ITimeFilter/IDemux/ITuner

Test: atest android.media.tv.tuner.cts on Cuttlefish
Bug: 174095851
Change-Id: I21ba3734602bd5246c2fb876e88cd2f77ec75632
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 383389f..f80f412 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -145,6 +145,7 @@
         "tuner/FilterClient.cpp",
         "tuner/FrontendClient.cpp",
         "tuner/LnbClient.cpp",
+        "tuner/TimeFilterClient.cpp",
         "tuner/TunerClient.cpp",
     ],
 
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index b91d347..70a55add 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -838,25 +838,6 @@
     mFilterClient = filterClient;
 }
 
-/////////////// TimeFilter ///////////////////////
-
-TimeFilter::TimeFilter(sp<ITimeFilter> sp, jobject obj) : mTimeFilterSp(sp) {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    mTimeFilterObj = env->NewWeakGlobalRef(obj);
-}
-
-TimeFilter::~TimeFilter() {
-    ALOGD("~TimeFilter");
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-
-    env->DeleteWeakGlobalRef(mTimeFilterObj);
-    mTimeFilterObj = NULL;
-}
-
-sp<ITimeFilter> TimeFilter::getITimeFilter() {
-    return mTimeFilterSp;
-}
-
 /////////////// FrontendClientCallbackImpl ///////////////////////
 
 FrontendClientCallbackImpl::FrontendClientCallbackImpl(jweak tunerObj) : mObject(tunerObj) {}
@@ -1101,8 +1082,6 @@
 
 /////////////// Tuner ///////////////////////
 
-sp<ITuner> JTuner::mTuner;
-sp<::android::hardware::tv::tuner::V1_1::ITuner> JTuner::mTuner_1_1;
 sp<TunerClient> JTuner::mTunerClient;
 
 JTuner::JTuner(JNIEnv *env, jobject thiz)
@@ -1112,10 +1091,6 @@
 
     mClass = (jclass)env->NewGlobalRef(clazz);
     mObject = env->NewWeakGlobalRef(thiz);
-    // TODO: remove after migrate to client lib
-    if (mTuner == NULL) {
-        mTuner = getTunerService();
-    }
     if (mTunerClient == NULL) {
         mTunerClient = new TunerClient();
     }
@@ -1125,15 +1100,13 @@
     if (mFeClient != NULL) {
         mFeClient->close();
     }
-    if (mDemux != NULL) {
-        mDemux->close();
+    if (mDemuxClient != NULL) {
+        mDemuxClient->close();
     }
     JNIEnv *env = AndroidRuntime::getJNIEnv();
 
     env->DeleteWeakGlobalRef(mObject);
     env->DeleteGlobalRef(mClass);
-    mTuner = NULL;
-    mDemux = NULL;
     mTunerClient = NULL;
     mFeClient = NULL;
     mDemuxClient = NULL;
@@ -1141,23 +1114,6 @@
     mObject = NULL;
 }
 
-sp<ITuner> JTuner::getTunerService() {
-    if (mTuner == nullptr) {
-        mTuner_1_1 = ::android::hardware::tv::tuner::V1_1::ITuner::getService();
-
-        if (mTuner_1_1 == nullptr) {
-            ALOGW("Failed to get tuner 1.1 service.");
-            mTuner = ITuner::getService();
-            if (mTuner == nullptr) {
-                ALOGW("Failed to get tuner 1.0 service.");
-            }
-        } else {
-            mTuner = static_cast<sp<ITuner>>(mTuner_1_1);
-         }
-     }
-     return mTuner;
-}
-
 jint JTuner::getTunerVersion() {
     ALOGD("JTuner::getTunerVersion()");
     return (jint) mTunerClient->getHalTunerVersion();
@@ -1551,56 +1507,27 @@
     return (int)result;
 }
 
-Result JTuner::openDemux() {
-    if (mTuner == nullptr || mTunerClient == nullptr) {
+Result JTuner::openDemux(int handle) {
+    if (mTunerClient == nullptr) {
         return Result::NOT_INITIALIZED;
     }
 
-    Result res = Result::SUCCESS;
-
-    if (mDemux == nullptr) {
-        uint32_t id;
-        sp<IDemux> demuxSp;
-        mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
-            demuxSp = demux;
-            id = demuxId;
-            res = r;
-            ALOGD("open demux, id = %d", demuxId);
-        });
-        if (res == Result::SUCCESS) {
-            mDemux = demuxSp;
-            mDemuxId = id;
-        } else {
-            return res;
-        }
-    }
-
-    // TODO: replace demux opening with mTunerClient->openDemux(handle)
-    // when DemuxClient is fully ready
     if (mDemuxClient == nullptr) {
-        sp<DemuxClient> demuxClient = new DemuxClient();
-        if (demuxClient == NULL) {
+        mDemuxClient = mTunerClient->openDemux(handle);
+        if (mDemuxClient == NULL) {
             ALOGE("Failed to open demux");
             return Result::UNKNOWN_ERROR;
         }
-        mDemuxClient = demuxClient;
-        mDemuxClient->setHidlDemux(mDemux);
         if (mFeClient != NULL) {
             mDemuxClient->setFrontendDataSource(mFeClient);
         }
     }
 
-    return res;
+    return Result::SUCCESS;
 }
 
 jint JTuner::close() {
     Result res = Result::SUCCESS;
-    if (mDemux != NULL) {
-        res = mDemux->close();
-        if (res != Result::SUCCESS) {
-            return (jint) res;
-        }
-    }
 
     if (mFeClient != NULL) {
         res = mFeClient->close();
@@ -1650,10 +1577,7 @@
 
 int JTuner::connectCiCam(jint id) {
     if (mDemuxClient == NULL) {
-        Result r = openDemux();
-        if (r != Result::SUCCESS) {
-            return (int) r;
-        }
+        return (int)Result::NOT_INITIALIZED;
     }
     Result r = mDemuxClient->connectCiCam((int)id);
     return (int) r;
@@ -1669,10 +1593,7 @@
 
 int JTuner::disconnectCiCam() {
     if (mDemuxClient == NULL) {
-        Result r = openDemux();
-        if (r != Result::SUCCESS) {
-            return (int) r;
-        }
+        return (int)Result::NOT_INITIALIZED;
     }
     Result r = mDemuxClient->disconnectCiCam();
     return (int) r;
@@ -1717,7 +1638,7 @@
 }
 
 jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
-    if (mDemux == NULL || mDemuxClient == NULL) {
+    if (mDemuxClient == NULL) {
         return NULL;
     }
 
@@ -1751,20 +1672,7 @@
 }
 
 jobject JTuner::openTimeFilter() {
-    if (mDemux == NULL) {
-        if (openDemux() != Result::SUCCESS) {
-            return NULL;
-        }
-    }
-    sp<ITimeFilter> iTimeFilterSp;
-    Result res;
-    mDemux->openTimeFilter(
-            [&](Result r, const sp<ITimeFilter>& filter) {
-                iTimeFilterSp = filter;
-                res = r;
-            });
-
-    if (res != Result::SUCCESS || iTimeFilterSp == NULL) {
+    if (mDemuxClient == NULL) {
         return NULL;
     }
 
@@ -1773,9 +1681,13 @@
             env->NewObject(
                     env->FindClass("android/media/tv/tuner/filter/TimeFilter"),
                     gFields.timeFilterInitID);
-    sp<TimeFilter> timeFilterSp = new TimeFilter(iTimeFilterSp, timeFilterObj);
-    timeFilterSp->incStrong(timeFilterObj);
-    env->SetLongField(timeFilterObj, gFields.timeFilterContext, (jlong)timeFilterSp.get());
+    sp<TimeFilterClient> timeFilterClient = mDemuxClient->openTimeFilter();
+    if (timeFilterClient == NULL) {
+        ALOGD("Failed to open time filter.");
+        return NULL;
+    }
+    timeFilterClient->incStrong(timeFilterObj);
+    env->SetLongField(timeFilterObj, gFields.timeFilterContext, (jlong)timeFilterClient.get());
 
     return timeFilterObj;
 }
@@ -1819,35 +1731,36 @@
 }
 
 jobject JTuner::getDemuxCaps() {
-    DemuxCapabilities caps;
-    Result res;
-    mTuner->getDemuxCaps([&](Result r, const DemuxCapabilities& demuxCaps) {
-        caps = demuxCaps;
-        res = r;
-    });
-    if (res != Result::SUCCESS) {
+    if (mTunerClient == NULL) {
         return NULL;
     }
+
+    shared_ptr<DemuxCapabilities> caps;
+    caps = mTunerClient->getDemuxCaps();
+    if (caps == NULL) {
+        return NULL;
+    }
+
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jclass clazz = env->FindClass("android/media/tv/tuner/DemuxCapabilities");
     jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIIIIIIJI[IZ)V");
 
-    jint numDemux = caps.numDemux;
-    jint numRecord = caps.numRecord;
-    jint numPlayback = caps.numPlayback;
-    jint numTsFilter = caps.numTsFilter;
-    jint numSectionFilter = caps.numSectionFilter;
-    jint numAudioFilter = caps.numAudioFilter;
-    jint numVideoFilter = caps.numVideoFilter;
-    jint numPesFilter = caps.numPesFilter;
-    jint numPcrFilter = caps.numPcrFilter;
-    jlong numBytesInSectionFilter = caps.numBytesInSectionFilter;
-    jint filterCaps = static_cast<jint>(caps.filterCaps);
-    jboolean bTimeFilter = caps.bTimeFilter;
+    jint numDemux = caps->numDemux;
+    jint numRecord = caps->numRecord;
+    jint numPlayback = caps->numPlayback;
+    jint numTsFilter = caps->numTsFilter;
+    jint numSectionFilter = caps->numSectionFilter;
+    jint numAudioFilter = caps->numAudioFilter;
+    jint numVideoFilter = caps->numVideoFilter;
+    jint numPesFilter = caps->numPesFilter;
+    jint numPcrFilter = caps->numPcrFilter;
+    jlong numBytesInSectionFilter = caps->numBytesInSectionFilter;
+    jint filterCaps = static_cast<jint>(caps->filterCaps);
+    jboolean bTimeFilter = caps->bTimeFilter;
 
-    jintArray linkCaps = env->NewIntArray(caps.linkCaps.size());
+    jintArray linkCaps = env->NewIntArray(caps->linkCaps.size());
     env->SetIntArrayRegion(
-            linkCaps, 0, caps.linkCaps.size(), reinterpret_cast<jint*>(&caps.linkCaps[0]));
+            linkCaps, 0, caps->linkCaps.size(), reinterpret_cast<jint*>(&caps->linkCaps[0]));
 
     return env->NewObject(clazz, capsInit, numDemux, numRecord, numPlayback, numTsFilter,
             numSectionFilter, numAudioFilter, numVideoFilter, numPesFilter, numPcrFilter,
@@ -2431,14 +2344,6 @@
 
 jint JTuner::closeDemux() {
     Result r = Result::SUCCESS;
-    if (mDemux != NULL) {
-        r = mDemux->close();
-    }
-    if (r == Result::SUCCESS) {
-        mDemux = NULL;
-    } else {
-        return (jint) r;
-    }
 
     if (mDemuxClient != NULL) {
         r = mDemuxClient->close();
@@ -3894,49 +3799,39 @@
     return (jint) filterClient->close();
 }
 
-static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) {
-    return (TimeFilter *)env->GetLongField(filter, gFields.timeFilterContext);
+static sp<TimeFilterClient> getTimeFilterClient(JNIEnv *env, jobject filter) {
+    return (TimeFilterClient *)env->GetLongField(filter, gFields.timeFilterContext);
 }
 
 static int android_media_tv_Tuner_time_filter_set_timestamp(
         JNIEnv *env, jobject filter, jlong timestamp) {
-    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
-    if (filterSp == NULL) {
-        ALOGD("Failed set timestamp: time filter not found");
+    sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
+    if (timeFilterClient == NULL) {
+        ALOGD("Failed set timestamp: time filter client not found");
         return (int) Result::INVALID_STATE;
     }
-    sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
-    Result r = iFilterSp->setTimeStamp(static_cast<uint64_t>(timestamp));
+    Result r = timeFilterClient->setTimeStamp(static_cast<uint64_t>(timestamp));
     return (int) r;
 }
 
 static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv *env, jobject filter) {
-    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
-    if (filterSp == NULL) {
-        ALOGD("Failed clear timestamp: time filter not found");
+    sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
+    if (timeFilterClient == NULL) {
+        ALOGD("Failed clear timestamp: time filter client not found");
         return (int) Result::INVALID_STATE;
     }
-    sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
-    Result r = iFilterSp->clearTimeStamp();
+    Result r = timeFilterClient->clearTimeStamp();
     return (int) r;
 }
 
 static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv *env, jobject filter) {
-    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
-    if (filterSp == NULL) {
-        ALOGD("Failed get timestamp: time filter not found");
+    sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
+    if (timeFilterClient == NULL) {
+        ALOGD("Failed get timestamp: time filter client not found");
         return NULL;
     }
-
-    sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
-    Result res;
-    uint64_t timestamp;
-    iFilterSp->getTimeStamp(
-            [&](Result r, uint64_t t) {
-                res = r;
-                timestamp = t;
-            });
-    if (res != Result::SUCCESS) {
+    uint64_t timestamp = timeFilterClient->getTimeStamp();
+    if (timestamp == (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP) {
         return NULL;
     }
 
@@ -3948,21 +3843,13 @@
 }
 
 static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv *env, jobject filter) {
-    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
-    if (filterSp == NULL) {
-        ALOGD("Failed get source time: time filter not found");
+    sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
+    if (timeFilterClient == NULL) {
+        ALOGD("Failed get source time: time filter client not found");
         return NULL;
     }
-
-    sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
-    Result res;
-    uint64_t timestamp;
-    iFilterSp->getSourceTime(
-            [&](Result r, uint64_t t) {
-                res = r;
-                timestamp = t;
-            });
-    if (res != Result::SUCCESS) {
+    uint64_t timestamp = timeFilterClient->getSourceTime();
+    if (timestamp == (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP) {
         return NULL;
     }
 
@@ -3974,15 +3861,15 @@
 }
 
 static int android_media_tv_Tuner_time_filter_close(JNIEnv *env, jobject filter) {
-    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
-    if (filterSp == NULL) {
-        ALOGD("Failed close time filter: time filter not found");
+    sp<TimeFilterClient> timeFilterClient = getTimeFilterClient(env, filter);
+    if (timeFilterClient == NULL) {
+        ALOGD("Failed close time filter: time filter client not found");
         return (int) Result::INVALID_STATE;
     }
 
-    Result r = filterSp->getITimeFilter()->close();
+    Result r = timeFilterClient->close();
     if (r == Result::SUCCESS) {
-        filterSp->decStrong(filter);
+        timeFilterClient->decStrong(filter);
         env->SetLongField(filter, gFields.timeFilterContext, 0);
     }
     return (int) r;
@@ -4057,9 +3944,9 @@
     return tuner->getDemuxCaps();
 }
 
-static jint android_media_tv_Tuner_open_demux(JNIEnv* env, jobject thiz, jint /* handle */) {
+static jint android_media_tv_Tuner_open_demux(JNIEnv* env, jobject thiz, jint handle) {
     sp<JTuner> tuner = getTuner(env, thiz);
-    return (jint) tuner->openDemux();
+    return (jint) tuner->openDemux(handle);
 }
 
 static jint android_media_tv_Tuner_close_tuner(JNIEnv* env, jobject thiz) {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index bbead26..0e30b18e 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -17,11 +17,6 @@
 #ifndef _ANDROID_MEDIA_TV_TUNER_H_
 #define _ANDROID_MEDIA_TV_TUNER_H_
 
-#include <android/hardware/tv/tuner/1.1/IFilter.h>
-#include <android/hardware/tv/tuner/1.1/IFilterCallback.h>
-#include <android/hardware/tv/tuner/1.1/IFrontend.h>
-#include <android/hardware/tv/tuner/1.1/IFrontendCallback.h>
-#include <android/hardware/tv/tuner/1.1/ITuner.h>
 #include <android/hardware/tv/tuner/1.1/types.h>
 
 #include <C2BlockInternal.h>
@@ -42,6 +37,7 @@
 #include "tuner/FrontendClientCallback.h"
 #include "tuner/LnbClient.h"
 #include "tuner/LnbClientCallback.h"
+#include "tuner/TimeFilterClient.h"
 #include "tuner/TunerClient.h"
 #include "jni.h"
 
@@ -65,17 +61,6 @@
 using ::android::hardware::tv::tuner::V1_0::FrontendScanType;
 using ::android::hardware::tv::tuner::V1_0::FrontendSettings;
 using ::android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1;
-using ::android::hardware::tv::tuner::V1_0::IDemux;
-using ::android::hardware::tv::tuner::V1_0::IDescrambler;
-using ::android::hardware::tv::tuner::V1_0::IDvr;
-using ::android::hardware::tv::tuner::V1_0::IDvrCallback;
-using ::android::hardware::tv::tuner::V1_0::IFilter;
-using ::android::hardware::tv::tuner::V1_1::IFilterCallback;
-using ::android::hardware::tv::tuner::V1_0::IFrontend;
-using ::android::hardware::tv::tuner::V1_0::ILnb;
-using ::android::hardware::tv::tuner::V1_0::ILnbCallback;
-using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
-using ::android::hardware::tv::tuner::V1_0::ITuner;
 using ::android::hardware::tv::tuner::V1_0::LnbEventType;
 using ::android::hardware::tv::tuner::V1_0::LnbId;
 using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
@@ -100,15 +85,6 @@
     jweak mLnbObj;
 };
 
-struct Lnb : public RefBase {
-    Lnb(sp<ILnb> sp, jobject obj);
-    ~Lnb();
-    sp<ILnb> getILnb();
-    // TODO: remove after migrate to client lib
-    sp<ILnb> mLnbSp;
-    jweak mLnbObj;
-};
-
 struct DvrClientCallbackImpl : public DvrClientCallback {
     ~DvrClientCallbackImpl();
     virtual void onRecordStatus(RecordStatus status);
@@ -189,19 +165,8 @@
     jweak mObject;
 };
 
-struct TimeFilter : public RefBase {
-    TimeFilter(sp<ITimeFilter> sp, jweak obj);
-    ~TimeFilter();
-    sp<ITimeFilter> getITimeFilter();
-    // TODO: remove after migrate to client lib
-    sp<ITimeFilter> mTimeFilterSp;
-    jweak mTimeFilterObj;
-};
-
 struct JTuner : public RefBase {
     JTuner(JNIEnv *env, jobject thiz);
-    // TODO: modify after migrate to client lib
-    sp<ITuner> getTunerService();
     int getTunerVersion();
     jobject getAvSyncHwId(sp<FilterClient> filter);
     jobject getAvSyncTime(jint id);
@@ -228,7 +193,7 @@
     jobject openDvr(DvrType type, jlong bufferSize);
     jobject getDemuxCaps();
     jobject getFrontendStatus(jintArray types);
-    Result openDemux();
+    Result openDemux(int handle);
     jint close();
     jint closeFrontend();
     jint closeDemux();
@@ -239,17 +204,11 @@
 private:
     jclass mClass;
     jweak mObject;
-    // TODO: remove after migrate to client lib
-    static sp<ITuner> mTuner;
-    static sp<::android::hardware::tv::tuner::V1_1::ITuner> mTuner_1_1;
     static sp<TunerClient> mTunerClient;
     sp<FrontendClient> mFeClient;
     int mFeId;
     sp<LnbClient> mLnbClient;
-    // TODO: remove after migrate to client lib
-    sp<IDemux> mDemux;
     sp<DemuxClient> mDemuxClient;
-    uint32_t mDemuxId;
     static jobject getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
     static jobject getAtsc3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
     static jobject getAtscFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
diff --git a/media/jni/tuner/DemuxClient.cpp b/media/jni/tuner/DemuxClient.cpp
index 58f9a46..08b7398 100644
--- a/media/jni/tuner/DemuxClient.cpp
+++ b/media/jni/tuner/DemuxClient.cpp
@@ -79,6 +79,21 @@
     return NULL;
 }
 
+sp<TimeFilterClient> DemuxClient::openTimeFilter() {
+    // TODO: pending aidl interface
+
+    if (mDemux != NULL) {
+        sp<ITimeFilter> hidlTimeFilter = openHidlTimeFilter();
+        if (hidlTimeFilter != NULL) {
+            sp<TimeFilterClient> timeFilterClient = new TimeFilterClient();
+            timeFilterClient->setHidlTimeFilter(hidlTimeFilter);
+            return timeFilterClient;
+        }
+    }
+
+    return NULL;
+}
+
 int DemuxClient::getAvSyncHwId(sp<FilterClient> filterClient) {
     // pending aidl interface
 
@@ -190,6 +205,26 @@
     return hidlFilter;
 }
 
+sp<ITimeFilter> DemuxClient::openHidlTimeFilter() {
+    if (mDemux == NULL) {
+        return NULL;
+    }
+
+    sp<ITimeFilter> timeFilter;
+    Result res;
+    mDemux->openTimeFilter(
+            [&](Result r, const sp<ITimeFilter>& timeFilterSp) {
+                timeFilter = timeFilterSp;
+                res = r;
+            });
+
+    if (res != Result::SUCCESS || timeFilter == NULL) {
+        return NULL;
+    }
+
+    return timeFilter;
+}
+
 sp<IDvr> DemuxClient::openHidlDvr(DvrType dvrType, int bufferSize,
         sp<HidlDvrCallback> callback) {
     if (mDemux == NULL) {
diff --git a/media/jni/tuner/DemuxClient.h b/media/jni/tuner/DemuxClient.h
index 7b8eede..2950dd4 100644
--- a/media/jni/tuner/DemuxClient.h
+++ b/media/jni/tuner/DemuxClient.h
@@ -26,12 +26,14 @@
 #include "FilterClient.h"
 #include "FilterClientCallback.h"
 #include "FrontendClient.h"
+#include "TimeFilterClient.h"
 
 //using ::aidl::android::media::tv::tuner::ITunerDemux;
 
 using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
 using ::android::hardware::tv::tuner::V1_0::DvrType;
 using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
 
 using namespace std;
 
@@ -56,7 +58,10 @@
      */
     sp<FilterClient> openFilter(DemuxFilterType type, int bufferSize, sp<FilterClientCallback> cb);
 
-    // TODO: handle TimeFilterClient
+    /**
+     * Open time filter of the demux.
+     */
+    sp<TimeFilterClient> openTimeFilter();
 
     /**
      * Get hardware sync ID for audio and video.
@@ -93,6 +98,7 @@
 
 private:
     sp<IFilter> openHidlFilter(DemuxFilterType type, int bufferSize, sp<HidlFilterCallback> cb);
+    sp<ITimeFilter> openHidlTimeFilter();
     sp<IDvr> openHidlDvr(DvrType type, int bufferSize, sp<HidlDvrCallback> cb);
 
     /**
diff --git a/media/jni/tuner/TimeFilterClient.cpp b/media/jni/tuner/TimeFilterClient.cpp
new file mode 100644
index 0000000..27ea6e5
--- /dev/null
+++ b/media/jni/tuner/TimeFilterClient.cpp
@@ -0,0 +1,115 @@
+/*
+ * 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 "TimeFilterClient"
+
+#include <android-base/logging.h>
+#include <utils/Log.h>
+
+#include "TimeFilterClient.h"
+
+using ::android::hardware::tv::tuner::V1_0::Result;
+using ::android::hardware::tv::tuner::V1_1::Constant64Bit;
+
+namespace android {
+
+/////////////// TimeFilterClient ///////////////////////
+
+// TODO: pending aidl interface
+TimeFilterClient::TimeFilterClient() {
+    //mTunerTimeFilter = tunerTimeFilter;
+}
+
+TimeFilterClient::~TimeFilterClient() {
+    //mTunerTimeFilter = NULL;
+    mTimeFilter = NULL;
+}
+
+// TODO: remove after migration to Tuner Service is done.
+void TimeFilterClient::setHidlTimeFilter(sp<ITimeFilter> timeFilter) {
+    mTimeFilter = timeFilter;
+}
+
+Result TimeFilterClient::setTimeStamp(long timeStamp) {
+    // TODO: pending aidl interface
+
+    if (mTimeFilter != NULL) {
+        return mTimeFilter->setTimeStamp(timeStamp);
+    }
+
+    return Result::INVALID_STATE;
+}
+
+Result TimeFilterClient::clearTimeStamp() {
+    // TODO: pending aidl interface
+
+    if (mTimeFilter != NULL) {
+        return mTimeFilter->clearTimeStamp();
+    }
+
+    return Result::INVALID_STATE;
+}
+
+long TimeFilterClient::getTimeStamp() {
+    // TODO: pending aidl interface
+
+    if (mTimeFilter != NULL) {
+        Result res;
+        long timestamp;
+        mTimeFilter->getTimeStamp(
+                [&](Result r, uint64_t t) {
+                    res = r;
+                    timestamp = t;
+                });
+        if (res != Result::SUCCESS) {
+            return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+        }
+        return timestamp;
+    }
+
+    return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+}
+
+long TimeFilterClient::getSourceTime() {
+    // TODO: pending aidl interface
+
+    if (mTimeFilter != NULL) {
+        Result res;
+        long timestamp;
+        mTimeFilter->getSourceTime(
+                [&](Result r, uint64_t t) {
+                    res = r;
+                    timestamp = t;
+                });
+        if (res != Result::SUCCESS) {
+            return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+        }
+        return timestamp;
+    }
+
+    return (long)Constant64Bit::INVALID_PRESENTATION_TIME_STAMP;
+}
+
+Result TimeFilterClient::close() {
+    // TODO: pending aidl interface
+
+    if (mTimeFilter != NULL) {
+        return mTimeFilter->close();
+    }
+
+    return Result::INVALID_STATE;
+}
+}  // namespace android
diff --git a/media/jni/tuner/TimeFilterClient.h b/media/jni/tuner/TimeFilterClient.h
new file mode 100644
index 0000000..9a9d172
--- /dev/null
+++ b/media/jni/tuner/TimeFilterClient.h
@@ -0,0 +1,88 @@
+/*
+ * 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_TV_TIME_FILTER_CLIENT_H_
+#define _ANDROID_MEDIA_TV_TIME_FILTER_CLIENT_H_
+
+//#include <aidl/android/media/tv/tuner/ITunerTimeFilter.h>
+#include <android/hardware/tv/tuner/1.0/ITimeFilter.h>
+#include <android/hardware/tv/tuner/1.1/types.h>
+
+//using ::aidl::android::media::tv::tuner::ITunerTimeFilter;
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+using namespace std;
+
+namespace android {
+
+struct TimeFilterClient : public RefBase {
+
+public:
+    // TODO: add TunerTimeFilter as parameter.
+    TimeFilterClient();
+    ~TimeFilterClient();
+
+    // TODO: remove after migration to Tuner Service is done.
+    void setHidlTimeFilter(sp<ITimeFilter> timeFilter);
+
+    /**
+     * Set time stamp for time based filter.
+     */
+    Result setTimeStamp(long timeStamp);
+
+    /**
+     * Clear the time stamp in the time filter.
+     */
+    Result clearTimeStamp();
+
+    /**
+     * Get the current time in the time filter.
+     */
+    long getTimeStamp();
+
+    /**
+     * Get the time from the beginning of current data source.
+     */
+    long getSourceTime();
+
+    /**
+     * Releases the Time Filter instance.
+     */
+    Result close();
+
+private:
+    /**
+     * An AIDL Tuner TimeFilter Singleton assigned at the first time the Tuner Client
+     * opens an TimeFilter. Default null when time filter is not opened.
+     */
+    // TODO: pending on aidl interface
+    //shared_ptr<ITunerTimeFilter> mTunerTimeFilter;
+
+    /**
+     * A TimeFilter HAL interface that is ready before migrating to the TunerTimeFilter.
+     * This is a temprary interface before Tuner Framework migrates to use TunerService.
+     * Default null when the HAL service does not exist.
+     */
+    sp<ITimeFilter> mTimeFilter;
+};
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_TV_TIME_FILTER_CLIENT_H_
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index e469aa3..b14e902 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -173,9 +173,22 @@
     return NULL;
 }
 
-DemuxCapabilities TunerClient::getDemuxCaps() {
-    DemuxCapabilities caps;
-    return caps;
+shared_ptr<DemuxCapabilities> TunerClient::getDemuxCaps() {
+    // pending aidl interface
+
+    if (mTuner != NULL) {
+        Result res;
+        DemuxCapabilities caps;
+        mTuner->getDemuxCaps([&](Result r, const DemuxCapabilities& demuxCaps) {
+            caps = demuxCaps;
+            res = r;
+        });
+        if (res == Result::SUCCESS) {
+            return make_shared<DemuxCapabilities>(caps);
+        }
+    }
+
+    return NULL;
 }
 
 sp<DescramblerClient> TunerClient::openDescrambler(int /*descramblerHandle*/) {
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
index 036360f..94fdf27 100644
--- a/media/jni/tuner/TunerClient.h
+++ b/media/jni/tuner/TunerClient.h
@@ -96,7 +96,7 @@
      *
      * @return the demux’s capabilities.
      */
-    DemuxCapabilities getDemuxCaps();
+    shared_ptr<DemuxCapabilities> getDemuxCaps();
 
     /**
      * Open a new interface of DescramblerClient given a descramblerHandle.