Refactor Tuner JNI and move the interaction with ILnb into LnbClient

Test: atest android.media.tv.tuner.cts on Cuttlefish
Bug: 174095851
Change-Id: I3903f62949aec0dac61388b356e7d7850a5a044c
diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java
index 5e95794..59ef4b8 100644
--- a/media/java/android/media/tv/tuner/Lnb.java
+++ b/media/java/android/media/tv/tuner/Lnb.java
@@ -145,7 +145,6 @@
 
     private static final String TAG = "Lnb";
 
-    int mId;
     LnbCallback mCallback;
     Executor mExecutor;
     Tuner mTuner;
@@ -162,9 +161,7 @@
     private Boolean mIsClosed = false;
     private final Object mLock = new Object();
 
-    private Lnb(int id) {
-        mId = id;
-    }
+    private Lnb() {}
 
     void setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner) {
         mCallback = callback;
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index e449fd2..9abd8fc 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -552,7 +552,7 @@
     private native int nativeStopTune();
     private native int nativeScan(int settingsType, FrontendSettings settings, int scanType);
     private native int nativeStopScan();
-    private native int nativeSetLnb(int lnbId);
+    private native int nativeSetLnb(Lnb lnb);
     private native int nativeSetLna(boolean enable);
     private native FrontendStatus nativeGetFrontendStatus(int[] statusTypes);
     private native Integer nativeGetAvSyncHwId(Filter filter);
@@ -825,7 +825,7 @@
      */
     @Result
     private int setLnb(@NonNull Lnb lnb) {
-        return nativeSetLnb(lnb.mId);
+        return nativeSetLnb(lnb);
     }
 
     /**
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index f9a84f7..5a18a4c 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -209,59 +209,46 @@
 }
 
 namespace android {
-/////////////// LnbCallback ///////////////////////
-LnbCallback::LnbCallback(jobject lnbObj, LnbId id) : mId(id) {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    mLnb = env->NewWeakGlobalRef(lnbObj);
-}
 
-LnbCallback::~LnbCallback() {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->DeleteWeakGlobalRef(mLnb);
-    mLnb = NULL;
-}
+/////////////// LnbClientCallbackImpl ///////////////////////
 
-Return<void> LnbCallback::onEvent(LnbEventType lnbEventType) {
-    ALOGD("LnbCallback::onEvent, type=%d", lnbEventType);
+void LnbClientCallbackImpl::onEvent(const LnbEventType lnbEventType) {
+    ALOGD("LnbClientCallbackImpl::onEvent, type=%d", lnbEventType);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     env->CallVoidMethod(
-            mLnb,
+            mLnbObj,
             gFields.onLnbEventID,
             (jint)lnbEventType);
-    return Void();
 }
-Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
-    ALOGD("LnbCallback::onDiseqcMessage");
+
+void LnbClientCallbackImpl::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
+    ALOGD("LnbClientCallbackImpl::onDiseqcMessage");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jbyteArray array = env->NewByteArray(diseqcMessage.size());
     env->SetByteArrayRegion(
             array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
 
     env->CallVoidMethod(
-            mLnb,
+            mLnbObj,
             gFields.onLnbDiseqcMessageID,
             array);
-    return Void();
 }
 
-/////////////// Lnb ///////////////////////
+void LnbClientCallbackImpl::setLnb(jweak lnbObj) {
+    ALOGD("LnbClientCallbackImpl::setLnb");
+    mLnbObj = lnbObj;
+}
 
-Lnb::Lnb(sp<ILnb> sp, jobject obj) : mLnbSp(sp) {
+LnbClientCallbackImpl::~LnbClientCallbackImpl() {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    mLnbObj = env->NewWeakGlobalRef(obj);
-}
-
-Lnb::~Lnb() {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    env->DeleteWeakGlobalRef(mLnbObj);
-    mLnbObj = NULL;
-}
-
-sp<ILnb> Lnb::getILnb() {
-    return mLnbSp;
+    if (mLnbObj != NULL) {
+        env->DeleteWeakGlobalRef(mLnbObj);
+        mLnbObj = NULL;
+    }
 }
 
 /////////////// DvrClientCallbackImpl ///////////////////////
+
 void DvrClientCallbackImpl::onRecordStatus(RecordStatus status) {
     ALOGD("DvrClientCallbackImpl::onRecordStatus");
     JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1470,63 +1457,63 @@
             maxSymbolRate, acquireRange, exclusiveGroupId, statusCaps, jcaps);
 }
 
-jobject JTuner::openLnbById(int id) {
-    sp<ILnb> iLnbSp;
-    Result r;
-    mTuner->openLnbById(id, [&](Result res, const sp<ILnb>& lnb) {
-        r = res;
-        iLnbSp = lnb;
-    });
-    if (r != Result::SUCCESS || iLnbSp == nullptr) {
-        ALOGE("Failed to open lnb");
+jobject JTuner::openLnbByHandle(int handle) {
+    if (mTunerClient == NULL) {
         return NULL;
     }
-    mLnb = iLnbSp;
+
+    sp<LnbClient> lnbClient;
+    sp<LnbClientCallbackImpl> callback = new LnbClientCallbackImpl();
+    lnbClient = mTunerClient->openLnb(handle);
+    if (lnbClient == NULL) {
+        ALOGD("Failed to open lnb, handle = %d", handle);
+        return NULL;
+    }
+
+    if (lnbClient->setCallback(callback) != Result::SUCCESS) {
+        ALOGD("Failed to set lnb callback");
+        return NULL;
+    }
 
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobject lnbObj = env->NewObject(
             env->FindClass("android/media/tv/tuner/Lnb"),
-            gFields.lnbInitID,
-            (jint) id);
+            gFields.lnbInitID);
 
-    sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id);
-    mLnb->setCallback(lnbCb);
-
-    sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj);
-    lnbSp->incStrong(lnbObj);
-    env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get());
+    lnbClient->incStrong(lnbObj);
+    env->SetLongField(lnbObj, gFields.lnbContext, (jlong)lnbClient.get());
+    callback->setLnb(env->NewWeakGlobalRef(lnbObj));
 
     return lnbObj;
 }
 
 jobject JTuner::openLnbByName(jstring name) {
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    std::string lnbName(env->GetStringUTFChars(name, nullptr));
-    sp<ILnb> iLnbSp;
-    Result res;
-    LnbId id;
-    mTuner->openLnbByName(lnbName, [&](Result r, LnbId lnbId, const sp<ILnb>& lnb) {
-        res = r;
-        iLnbSp = lnb;
-        id = lnbId;
-    });
-    if (res != Result::SUCCESS || iLnbSp == nullptr) {
-        ALOGE("Failed to open lnb");
+    if (mTunerClient == NULL) {
         return NULL;
     }
-    mLnb = iLnbSp;
+
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    std::string lnbName(env->GetStringUTFChars(name, nullptr));
+    sp<LnbClient> lnbClient;
+    sp<LnbClientCallbackImpl> callback = new LnbClientCallbackImpl();
+    lnbClient = mTunerClient->openLnbByName(lnbName);
+    if (lnbClient == NULL) {
+        ALOGD("Failed to open lnb by name, name = %s", lnbName.c_str());
+        return NULL;
+    }
+
+    if (lnbClient->setCallback(callback) != Result::SUCCESS) {
+        ALOGD("Failed to set lnb callback");
+        return NULL;
+    }
 
     jobject lnbObj = env->NewObject(
             env->FindClass("android/media/tv/tuner/Lnb"),
-            gFields.lnbInitID,
-            id);
+            gFields.lnbInitID);
 
-    sp<LnbCallback> lnbCb = new LnbCallback(lnbObj, id);
-    mLnb->setCallback(lnbCb);
-
-    sp<Lnb> lnbSp = new Lnb(iLnbSp, lnbObj);
-    lnbSp->incStrong(lnbObj);
-    env->SetLongField(lnbObj, gFields.lnbContext, (jlong) lnbSp.get());
+    lnbClient->incStrong(lnbObj);
+    env->SetLongField(lnbObj, gFields.lnbContext, (jlong)lnbClient.get());
+    callback->setLnb(env->NewWeakGlobalRef(lnbObj));
 
     return lnbObj;
 }
@@ -1575,12 +1562,16 @@
     return (int)result;
 }
 
-int JTuner::setLnb(int id) {
-    if (mFe == NULL) {
-        ALOGE("frontend is not initialized");
+int JTuner::setLnb(sp<LnbClient> lnbClient) {
+    if (mFeClient == NULL) {
+        ALOGE("frontend client is not initialized");
         return (int)Result::INVALID_STATE;
     }
-    Result result = mFe->setLnb(id);
+    if (lnbClient == NULL) {
+        ALOGE("lnb is not initialized");
+        return (int)Result::INVALID_STATE;
+    }
+    Result result = mFeClient->setLnb(lnbClient);
     return (int)result;
 }
 
@@ -3199,6 +3190,10 @@
     return (FilterClient *)env->GetLongField(filter, gFields.filterContext);
 }
 
+static sp<LnbClient> getLnbClient(JNIEnv *env, jobject lnb) {
+    return (LnbClient *)env->GetLongField(lnb, gFields.lnbContext);
+}
+
 static DvrSettings getDvrSettings(JNIEnv *env, jobject settings, bool isRecorder) {
     DvrSettings dvrSettings;
     jclass clazz = env->FindClass("android/media/tv/tuner/dvr/DvrSettings");
@@ -3262,7 +3257,7 @@
 
     jclass lnbClazz = env->FindClass("android/media/tv/tuner/Lnb");
     gFields.lnbContext = env->GetFieldID(lnbClazz, "mNativeContext", "J");
-    gFields.lnbInitID = env->GetMethodID(lnbClazz, "<init>", "(I)V");
+    gFields.lnbInitID = env->GetMethodID(lnbClazz, "<init>", "()V");
     gFields.onLnbEventID = env->GetMethodID(lnbClazz, "onEvent", "(I)V");
     gFields.onLnbDiseqcMessageID = env->GetMethodID(lnbClazz, "onDiseqcMessage", "([B)V");
 
@@ -3351,9 +3346,14 @@
     return tuner->stopScan();
 }
 
-static int android_media_tv_Tuner_set_lnb(JNIEnv *env, jobject thiz, jint id) {
+static int android_media_tv_Tuner_set_lnb(JNIEnv *env, jobject thiz, jobject lnb) {
     sp<JTuner> tuner = getTuner(env, thiz);
-    return tuner->setLnb(id);
+    sp<LnbClient> lnbClient = getLnbClient(env, lnb);
+    if (lnbClient == NULL) {
+        ALOGE("lnb is not initialized");
+        return (int)Result::INVALID_STATE;
+    }
+    return tuner->setLnb(lnbClient);
 }
 
 static int android_media_tv_Tuner_set_lna(JNIEnv *env, jobject thiz, jboolean enable) {
@@ -3410,8 +3410,7 @@
 
 static jobject android_media_tv_Tuner_open_lnb_by_handle(JNIEnv *env, jobject thiz, jint handle) {
     sp<JTuner> tuner = getTuner(env, thiz);
-    uint32_t id = getResourceIdFromHandle(handle);
-    return tuner->openLnbById(id);
+    return tuner->openLnbByHandle(handle);
 }
 
 static jobject android_media_tv_Tuner_open_lnb_by_name(JNIEnv *env, jobject thiz, jstring name) {
@@ -4259,42 +4258,38 @@
     return (jint) dvrClient->close();
 }
 
-static sp<Lnb> getLnb(JNIEnv *env, jobject lnb) {
-    return (Lnb *)env->GetLongField(lnb, gFields.lnbContext);
-}
-
 static jint android_media_tv_Tuner_lnb_set_voltage(JNIEnv* env, jobject lnb, jint voltage) {
-    sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
-    Result r = iLnbSp->setVoltage(static_cast<LnbVoltage>(voltage));
+    sp<LnbClient> lnbClient = getLnbClient(env, lnb);
+    Result r = lnbClient->setVoltage(static_cast<LnbVoltage>(voltage));
     return (jint) r;
 }
 
 static int android_media_tv_Tuner_lnb_set_tone(JNIEnv* env, jobject lnb, jint tone) {
-    sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
-    Result r = iLnbSp->setTone(static_cast<LnbTone>(tone));
+    sp<LnbClient> lnbClient = getLnbClient(env, lnb);
+    Result r = lnbClient->setTone(static_cast<LnbTone>(tone));
     return (jint) r;
 }
 
 static int android_media_tv_Tuner_lnb_set_position(JNIEnv* env, jobject lnb, jint position) {
-    sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
-    Result r = iLnbSp->setSatellitePosition(static_cast<LnbPosition>(position));
+    sp<LnbClient> lnbClient = getLnbClient(env, lnb);
+    Result r = lnbClient->setSatellitePosition(static_cast<LnbPosition>(position));
     return (jint) r;
 }
 
 static int android_media_tv_Tuner_lnb_send_diseqc_msg(JNIEnv* env, jobject lnb, jbyteArray msg) {
-    sp<ILnb> iLnbSp = getLnb(env, lnb)->getILnb();
+    sp<LnbClient> lnbClient = getLnbClient(env, lnb);
     int size = env->GetArrayLength(msg);
     std::vector<uint8_t> v(size);
     env->GetByteArrayRegion(msg, 0, size, reinterpret_cast<jbyte*>(&v[0]));
-    Result r = iLnbSp->sendDiseqcMessage(v);
+    Result r = lnbClient->sendDiseqcMessage(v);
     return (jint) r;
 }
 
 static int android_media_tv_Tuner_close_lnb(JNIEnv* env, jobject lnb) {
-    sp<Lnb> lnbSp = getLnb(env, lnb);
-    Result r = lnbSp->getILnb()->close();
+    sp<LnbClient> lnbClient = getLnbClient(env, lnb);
+    Result r = lnbClient->close();
     if (r == Result::SUCCESS) {
-        lnbSp->decStrong(lnb);
+        lnbClient->decStrong(lnb);
         env->SetLongField(lnb, gFields.lnbContext, 0);
     }
     return (jint) r;
@@ -4433,7 +4428,7 @@
     { "nativeScan", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;I)I",
             (void *)android_media_tv_Tuner_scan },
     { "nativeStopScan", "()I", (void *)android_media_tv_Tuner_stop_scan },
-    { "nativeSetLnb", "(I)I", (void *)android_media_tv_Tuner_set_lnb },
+    { "nativeSetLnb", "(Landroid/media/tv/tuner/Lnb;)I", (void *)android_media_tv_Tuner_set_lnb },
     { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna },
     { "nativeGetFrontendStatus", "([I)Landroid/media/tv/tuner/frontend/FrontendStatus;",
             (void *)android_media_tv_Tuner_get_frontend_status },
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 8fffb2a..b0613d4 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -35,10 +35,13 @@
 #include <utils/RefBase.h>
 
 #include "tuner/DemuxClient.h"
+#include "tuner/DescramblerClient.h"
 #include "tuner/FilterClient.h"
 #include "tuner/FilterClientCallback.h"
 #include "tuner/FrontendClient.h"
 #include "tuner/FrontendClientCallback.h"
+#include "tuner/LnbClient.h"
+#include "tuner/LnbClientCallback.h"
 #include "tuner/TunerClient.h"
 #include "jni.h"
 
@@ -87,13 +90,14 @@
 
 namespace android {
 
-struct LnbCallback : public ILnbCallback {
-    LnbCallback(jweak tunerObj, LnbId id);
-    ~LnbCallback();
-    virtual Return<void> onEvent(LnbEventType lnbEventType);
-    virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
-    jweak mLnb;
-    LnbId mId;
+struct LnbClientCallbackImpl : public LnbClientCallback {
+    ~LnbClientCallbackImpl();
+    virtual void onEvent(LnbEventType lnbEventType);
+    virtual void onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
+
+    void setLnb(jweak lnbObj);
+private:
+    jweak mLnbObj;
 };
 
 struct Lnb : public RefBase {
@@ -215,9 +219,9 @@
     int scan(const FrontendSettings& settings, FrontendScanType scanType,
             const FrontendSettingsExt1_1& settingsExt1_1);
     int stopScan();
-    int setLnb(int id);
+    int setLnb(sp<LnbClient> lnbClient);
     int setLna(bool enable);
-    jobject openLnbById(int id);
+    jobject openLnbByHandle(int handle);
     jobject openLnbByName(jstring name);
     jobject openFilter(DemuxFilterType type, int bufferSize);
     jobject openTimeFilter();
@@ -246,8 +250,7 @@
     sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFe_1_1;
     sp<FrontendClient> mFeClient;
     int mFeId;
-    // TODO: remove after migrate to client lib
-    sp<ILnb> mLnb;
+    sp<LnbClient> mLnbClient;
     // TODO: remove after migrate to client lib
     sp<IDemux> mDemux;
     sp<DemuxClient> mDemuxClient;
diff --git a/media/jni/tuner/FrontendClient.cpp b/media/jni/tuner/FrontendClient.cpp
index b6225cf..9dd4df7 100644
--- a/media/jni/tuner/FrontendClient.cpp
+++ b/media/jni/tuner/FrontendClient.cpp
@@ -99,6 +99,21 @@
     return Result::INVALID_STATE;
 }
 
+Result FrontendClient::setLnb(sp<LnbClient> lnbClient) {
+    if (mTunerFrontend != NULL) {
+        // TODO: handle error message.
+        /*mTunerFrontend->setLnb(lnbClient->getAidlLnb());
+        return Result::SUCCESS;*/
+    }
+
+    if (mFrontend != NULL) {
+        Result result = mFrontend->setLnb(lnbClient->getId());
+        return result;
+    }
+
+    return Result::INVALID_STATE;
+}
+
 Result FrontendClient::close() {
     if (mTunerFrontend != NULL) {
         // TODO: handle error message.
diff --git a/media/jni/tuner/FrontendClient.h b/media/jni/tuner/FrontendClient.h
index 265e14f..b24f944 100644
--- a/media/jni/tuner/FrontendClient.h
+++ b/media/jni/tuner/FrontendClient.h
@@ -24,6 +24,7 @@
 #include <android/hardware/tv/tuner/1.1/types.h>
 
 #include "FrontendClientCallback.h"
+#include "LnbClient.h"
 
 using Status = ::ndk::ScopedAStatus;
 
@@ -127,6 +128,11 @@
     Result stopTune();
 
     /**
+     * Sets Low-Noise Block downconverter (LNB) for satellite frontend.
+     */
+    Result setLnb(sp<LnbClient> lnbClient);
+
+    /**
      * Close Frontend.
      */
     Result close();
diff --git a/media/jni/tuner/LnbClient.cpp b/media/jni/tuner/LnbClient.cpp
index c9f9f84..7f3916f 100644
--- a/media/jni/tuner/LnbClient.cpp
+++ b/media/jni/tuner/LnbClient.cpp
@@ -30,11 +30,13 @@
 // TODO: pending aidl interface
 LnbClient::LnbClient() {
     //mTunerLnb = tunerLnb;
+    mId = -1;
 }
 
 LnbClient::~LnbClient() {
     //mTunerLnb = NULL;
     mLnb = NULL;
+    mId = -1;
 }
 
 // TODO: remove after migration to Tuner Service is done.
@@ -42,28 +44,66 @@
     mLnb = lnb;
 }
 
-Result LnbClient::setCallback(sp<LnbClientCallback> /*cb*/) {
-    return Result::SUCCESS;
+Result LnbClient::setCallback(sp<LnbClientCallback> cb) {
+    // TODO: pending aidl interface
+    /*if (mTunerFrontend != NULL) {
+        mAidlCallback = ::ndk::SharedRefBase::make<TunerLnbCallback>(cb);
+        mTunerLnb->setCallback(mAidlCallback);
+        return Result::SUCCESS;
+    }*/
+
+    mHidlCallback = new HidlLnbCallback(cb);
+    return mLnb->setCallback(mHidlCallback);
 }
 
-Result LnbClient::setVoltage(int /*voltage*/) {
-    return Result::SUCCESS;
+Result LnbClient::setVoltage(LnbVoltage voltage) {
+    // TODO: pending aidl interface
+
+    if (mLnb != NULL) {
+        return mLnb->setVoltage(voltage);
+    }
+
+    return Result::INVALID_STATE;
 }
 
-Result LnbClient::setTone(int /*tone*/) {
-    return Result::SUCCESS;
+Result LnbClient::setTone(LnbTone tone) {
+    // TODO: pending aidl interface
+
+    if (mLnb != NULL) {
+        return mLnb->setTone(tone);
+    }
+
+    return Result::INVALID_STATE;
 }
 
-Result LnbClient::setSatellitePosition(int /*position*/) {
-    return Result::SUCCESS;
+Result LnbClient::setSatellitePosition(LnbPosition position) {
+    // TODO: pending aidl interface
+
+    if (mLnb != NULL) {
+        return mLnb->setSatellitePosition(position);
+    }
+
+    return Result::INVALID_STATE;
 }
 
-Result LnbClient::sendDiseqcMessage(vector<uint8_t> /*diseqcMessage*/) {
-    return Result::SUCCESS;
+Result LnbClient::sendDiseqcMessage(vector<uint8_t> diseqcMessage) {
+    // TODO: pending aidl interface
+
+    if (mLnb != NULL) {
+        return mLnb->sendDiseqcMessage(diseqcMessage);
+    }
+
+    return Result::INVALID_STATE;
 }
 
 Result LnbClient::close() {
-    return Result::SUCCESS;
+    // TODO: pending aidl interface
+
+    if (mLnb != NULL) {
+        return mLnb->close();
+    }
+
+    return Result::INVALID_STATE;
 }
 
 /////////////// ILnbCallback ///////////////////////
diff --git a/media/jni/tuner/LnbClient.h b/media/jni/tuner/LnbClient.h
index c548777..533a996 100644
--- a/media/jni/tuner/LnbClient.h
+++ b/media/jni/tuner/LnbClient.h
@@ -31,6 +31,10 @@
 using ::android::hardware::hidl_vec;
 using ::android::hardware::tv::tuner::V1_0::ILnb;
 using ::android::hardware::tv::tuner::V1_0::ILnbCallback;
+using ::android::hardware::tv::tuner::V1_0::LnbId;
+using ::android::hardware::tv::tuner::V1_0::LnbPosition;
+using ::android::hardware::tv::tuner::V1_0::LnbTone;
+using ::android::hardware::tv::tuner::V1_0::LnbVoltage;
 using ::android::hardware::tv::tuner::V1_0::Result;
 
 using namespace std;
@@ -79,17 +83,17 @@
     /**
      * Set the lnb's power voltage.
      */
-    Result setVoltage(int voltage);
+    Result setVoltage(LnbVoltage voltage);
 
     /**
      * Set the lnb's tone mode.
      */
-    Result setTone(int tone);
+    Result setTone(LnbTone tone);
 
     /**
      * Select the lnb's position.
      */
-    Result setSatellitePosition(int position);
+    Result setSatellitePosition(LnbPosition position);
 
     /**
      * Sends DiSEqC (Digital Satellite Equipment Control) message.
@@ -101,6 +105,10 @@
      */
     Result close();
 
+    //shared_ptr<ITunerLnb> getAidlLnb() { return mTunerLnb; }
+    void setId(LnbId id) { mId = id; }
+    LnbId getId() { return mId; }
+
 private:
     /**
      * An AIDL Tuner Lnb Singleton assigned at the first time the Tuner Client
@@ -115,6 +123,11 @@
      * Default null when the HAL service does not exist.
      */
     sp<ILnb> mLnb;
+
+    //shared_ptr<TunerLnbCallback> mAidlCallback;
+    sp<HidlLnbCallback> mHidlCallback;
+
+    LnbId mId;
 };
 }  // namespace android
 
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index 67a559c..69cd3d3 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -180,11 +180,49 @@
     return NULL;
 }
 
-sp<LnbClient> TunerClient::openLnb(int /*lnbHandle*/) {
+sp<LnbClient> TunerClient::openLnb(int lnbHandle) {
+    if (mTunerService != NULL) {
+        // TODO: handle error code
+        /*shared_ptr<ITunerLnb> tunerLnb;
+        mTunerService->openLnb(demuxHandle, &tunerLnb);
+        return new LnbClient(tunerLnb);*/
+    }
+
+    if (mTuner != NULL) {
+        int id = getResourceIdFromHandle(lnbHandle, LNB);
+        // TODO: pending aidl interface
+        sp<LnbClient> lnbClient = new LnbClient();
+        sp<ILnb> hidlLnb = openHidlLnbById(id);
+        if (hidlLnb != NULL) {
+            lnbClient->setHidlLnb(hidlLnb);
+            lnbClient->setId(id);
+            return lnbClient;
+        }
+    }
+
     return NULL;
 }
 
-sp<LnbClient> TunerClient::openLnbByName(string /*lnbName*/) {
+sp<LnbClient> TunerClient::openLnbByName(string lnbName) {
+    if (mTunerService != NULL) {
+        // TODO: handle error code
+        /*shared_ptr<ITunerLnb> tunerLnb;
+        mTunerService->openLnbByName(lnbName, &tunerLnb);
+        return new LnbClient(tunerLnb);*/
+    }
+
+    if (mTuner != NULL) {
+        // TODO: pending aidl interface
+        sp<LnbClient> lnbClient = new LnbClient();
+        LnbId id;
+        sp<ILnb> hidlLnb = openHidlLnbByName(lnbName, id);
+        if (hidlLnb != NULL) {
+            lnbClient->setHidlLnb(hidlLnb);
+            lnbClient->setId(id);
+            return lnbClient;
+        }
+    }
+
     return NULL;
 }
 
@@ -249,6 +287,37 @@
     return demux;
 }
 
+sp<ILnb> TunerClient::openHidlLnbById(int id) {
+    sp<ILnb> lnb;
+    Result res;
+
+    mTuner->openLnbById(id, [&](Result r, const sp<ILnb>& lnbSp) {
+        res = r;
+        lnb = lnbSp;
+    });
+    if (res != Result::SUCCESS || lnb == nullptr) {
+        ALOGE("Failed to open lnb by id");
+        return NULL;
+    }
+    return lnb;
+}
+
+sp<ILnb> TunerClient::openHidlLnbByName(string name, LnbId& lnbId) {
+    sp<ILnb> lnb;
+    Result res;
+
+    mTuner->openLnbByName(name, [&](Result r, LnbId id, const sp<ILnb>& lnbSp) {
+        res = r;
+        lnb = lnbSp;
+        lnbId = id;
+    });
+    if (res != Result::SUCCESS || lnb == nullptr) {
+        ALOGE("Failed to open lnb by name");
+        return NULL;
+    }
+    return lnb;
+}
+
 FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo) {
     FrontendInfo hidlFrontendInfo {
         .type = static_cast<FrontendType>(aidlFrontendInfo.type),
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
index 98ae24d..06ba7a5 100644
--- a/media/jni/tuner/TunerClient.h
+++ b/media/jni/tuner/TunerClient.h
@@ -133,6 +133,8 @@
     sp<IFrontend> openHidlFrontendById(int id);
     sp<IDemux> openHidlDemux();
     Result getHidlFrontendInfo(int id, FrontendInfo& info);
+    sp<ILnb> openHidlLnbById(int id);
+    sp<ILnb> openHidlLnbByName(string name, LnbId& lnbId);
     FrontendInfo FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo);
 
     int getResourceIdFromHandle(int handle, int resourceType);