Add ILnb VTS tests

Test: atest VtsHalTvTunerV1_0TargetTest
Bug: 157955950
Change-Id: Icc2fca6f65e48a05c916a9629913cc7b18a8fd80
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index da56041..b74f6ec 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -124,12 +124,12 @@
     }
 
     if (!mPcrFilterIds.empty()) {
-        ALOGE("[Demux] No PCR filter opened.");
         // Return the lowest pcr filter id in the default implementation as the av sync id
         _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
         return Void();
     }
 
+    ALOGE("[Demux] No PCR filter opened.");
     _hidl_cb(Result::INVALID_STATE, avSyncHwId);
     return Void();
 }
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index 8c08873..1765915 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -24,6 +24,7 @@
         "FilterTests.cpp",
         "DvrTests.cpp",
         "DescramblerTests.cpp",
+        "LnbTests.cpp",
     ],
     static_libs: [
         "android.hardware.cas@1.0",
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.cpp b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
index 393bab5..37a47d7 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
@@ -53,23 +53,23 @@
     return AssertionResult(status.isOk());
 }
 
-void DemuxTests::getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId) {
-    ASSERT_TRUE(mDemux) << "Demux is not opened yet.";
+AssertionResult DemuxTests::getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId) {
+    EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
     Result status;
     mDemux->getAvSyncHwId(filter, [&](Result result, uint32_t id) {
         status = result;
         avSyncHwId = id;
     });
-    ASSERT_TRUE(status == Result::SUCCESS) << "Fail to get avSyncHwId.";
+    return AssertionResult(status == Result::SUCCESS);
 }
 
-void DemuxTests::getAvSyncTime(uint32_t avSyncId) {
-    ASSERT_TRUE(mDemux) << "Demux is not opened yet.";
+AssertionResult DemuxTests::getAvSyncTime(uint32_t avSyncId) {
+    EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
     Result status;
     uint64_t syncTime;
     mDemux->getAvSyncTime(avSyncId, [&](Result result, uint64_t time) {
         status = result;
         syncTime = time;
     });
-    ASSERT_TRUE(status == Result::SUCCESS) << "Fail to get avSyncTime.";
+    return AssertionResult(status == Result::SUCCESS);
 }
\ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.h b/tv/tuner/1.0/vts/functional/DemuxTests.h
index 4211ca7..b249ea8 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.h
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.h
@@ -44,8 +44,8 @@
 
     AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId);
     AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
-    void getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId);
-    void getAvSyncTime(uint32_t avSyncId);
+    AssertionResult getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId);
+    AssertionResult getAvSyncTime(uint32_t avSyncId);
     AssertionResult getDemuxCaps(DemuxCapabilities& demuxCaps);
     AssertionResult closeDemux();
 
diff --git a/tv/tuner/1.0/vts/functional/DescramblerTests.h b/tv/tuner/1.0/vts/functional/DescramblerTests.h
index 31f4663..16d480d 100644
--- a/tv/tuner/1.0/vts/functional/DescramblerTests.h
+++ b/tv/tuner/1.0/vts/functional/DescramblerTests.h
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/cas/1.0/types.h>
 #include <android/hardware/cas/1.2/ICas.h>
@@ -28,6 +26,8 @@
 #include <android/hardware/tv/tuner/1.0/ITuner.h>
 #include <android/hardware/tv/tuner/1.0/types.h>
 #include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
 #include <hidl/Status.h>
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
@@ -69,6 +69,8 @@
 
 using ::testing::AssertionResult;
 
+using namespace std;
+
 class MediaCasListener : public ICasListener {
   public:
     virtual Return<void> onEvent(int32_t /*event*/, int32_t /*arg*/,
diff --git a/tv/tuner/1.0/vts/functional/LnbTests.cpp b/tv/tuner/1.0/vts/functional/LnbTests.cpp
new file mode 100644
index 0000000..9080f59
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/LnbTests.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#include "LnbTests.h"
+
+Return<void> LnbCallback::onEvent(LnbEventType lnbEventType) {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    ALOGD("[vts] lnb event received. Type: %d", lnbEventType);
+    mEventReceived = true;
+    mMsgCondition.signal();
+    return Void();
+}
+
+Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
+    string msg(diseqcMessage.begin(), diseqcMessage.end());
+    ALOGD("[vts] onDiseqcMessage %s", msg.c_str());
+    return Void();
+}
+
+AssertionResult LnbTests::getLnbIds(vector<uint32_t>& ids) {
+    Result status;
+    mService->getLnbIds([&](Result result, const hidl_vec<uint32_t>& lnbIds) {
+        status = result;
+        ids = lnbIds;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::openLnbById(uint32_t lnbId) {
+    Result status;
+    mService->openLnbById(lnbId, [&](Result result, const sp<ILnb>& lnb) {
+        mLnb = lnb;
+        status = result;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::openLnbByName(string lnbName) {
+    Result status;
+    mService->openLnbByName(lnbName, [&](Result result, uint32_t /*lnbId*/, const sp<ILnb>& lnb) {
+        mLnb = lnb;
+        status = result;
+    });
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::setLnbCallback() {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    mLnbCallback = new LnbCallback();
+    auto callbackStatus = mLnb->setCallback(mLnbCallback);
+    return AssertionResult(callbackStatus.isOk());
+}
+
+AssertionResult LnbTests::setVoltage(LnbVoltage voltage) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->setVoltage(voltage);
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::setTone(LnbTone tone) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->setTone(tone);
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::setSatellitePosition(LnbPosition position) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->setSatellitePosition(position);
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::sendDiseqcMessage(vector<uint8_t> diseqcMsg) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->sendDiseqcMessage(diseqcMsg);
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::closeLnb() {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->close();
+    mLnb = nullptr;
+    mLnbCallback = nullptr;
+    return AssertionResult(status == Result::SUCCESS);
+}
diff --git a/tv/tuner/1.0/vts/functional/LnbTests.h b/tv/tuner/1.0/vts/functional/LnbTests.h
new file mode 100644
index 0000000..2fdbe2c
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/LnbTests.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/ILnb.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::ILnb;
+using android::hardware::tv::tuner::V1_0::ILnbCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::LnbEventType;
+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 ::testing::AssertionResult;
+
+using namespace std;
+
+class LnbCallback : public ILnbCallback {
+  public:
+    virtual Return<void> onEvent(LnbEventType lnbEventType) override;
+    virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) override;
+
+  private:
+    bool mEventReceived = false;
+    android::Mutex mMsgLock;
+    android::Condition mMsgCondition;
+};
+
+class LnbTests {
+  public:
+    void setService(sp<ITuner> tuner) { mService = tuner; }
+
+    AssertionResult getLnbIds(vector<uint32_t>& ids);
+    AssertionResult openLnbById(uint32_t lnbId);
+    AssertionResult openLnbByName(string lnbName);
+    AssertionResult setLnbCallback();
+    AssertionResult setVoltage(LnbVoltage voltage);
+    AssertionResult setTone(LnbTone tone);
+    AssertionResult setSatellitePosition(LnbPosition position);
+    AssertionResult sendDiseqcMessage(vector<uint8_t> diseqcMsg);
+    AssertionResult closeLnb();
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    sp<ITuner> mService;
+    sp<ILnb> mLnb;
+    sp<LnbCallback> mLnbCallback;
+    hidl_vec<uint32_t> mLnbIds;
+};
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 882a511..583fce9 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -275,6 +275,22 @@
     mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
 }
 
+TEST_P(TunerLnbHidlTest, SendDiseqcMessageToLnb) {
+    description("Open and configure an Lnb with specific settings then send a diseqc msg to it.");
+    vector<uint32_t> ids;
+    ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+    if (ids.size() == 0) {
+        return;
+    }
+    ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+    ASSERT_TRUE(mLnbTests.setLnbCallback());
+    ASSERT_TRUE(mLnbTests.setVoltage(lnbArray[LNB0].voltage));
+    ASSERT_TRUE(mLnbTests.setTone(lnbArray[LNB0].tone));
+    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbArray[LNB0].position));
+    ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgArray[DISEQC_POWER_ON]));
+    ASSERT_TRUE(mLnbTests.closeLnb());
+}
+
 TEST_P(TunerDemuxHidlTest, openDemux) {
     description("Open and close a Demux.");
     uint32_t feId;
@@ -429,6 +445,11 @@
         android::hardware::PrintInstanceNameToString);
 
 INSTANTIATE_TEST_SUITE_P(
+        PerInstance, TunerLnbHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
         PerInstance, TunerDemuxHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
         android::hardware::PrintInstanceNameToString);
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 2bdb537..c8a23aa 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -18,6 +18,7 @@
 #include "DescramblerTests.h"
 #include "DvrTests.h"
 #include "FrontendTests.h"
+#include "LnbTests.h"
 
 using android::hardware::tv::tuner::V1_0::DataFormat;
 using android::hardware::tv::tuner::V1_0::IDescrambler;
@@ -31,6 +32,7 @@
 void initConfiguration() {
     initFrontendConfig();
     initFrontendScanConfig();
+    initLnbConfig();
     initFilterConfig();
     initDvrConfig();
     initDescramblerConfig();
@@ -65,6 +67,25 @@
     FrontendTests mFrontendTests;
 };
 
+class TunerLnbHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        mService = ITuner::getService(GetParam());
+        ASSERT_NE(mService, nullptr);
+        initConfiguration();
+
+        mLnbTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    sp<ITuner> mService;
+    LnbTests mLnbTests;
+};
+
 class TunerDemuxHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 9f24eef..1941773 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -47,6 +47,9 @@
 using android::hardware::tv::tuner::V1_0::FrontendStatus;
 using android::hardware::tv::tuner::V1_0::FrontendStatusType;
 using android::hardware::tv::tuner::V1_0::FrontendType;
+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::PlaybackSettings;
 using android::hardware::tv::tuner::V1_0::RecordSettings;
 
@@ -95,6 +98,16 @@
 } Frontend;
 
 typedef enum {
+    LNB0,
+    LNB_MAX,
+} Lnb;
+
+typedef enum {
+    DISEQC_POWER_ON,
+    DISEQC_MAX,
+} Diseqc;
+
+typedef enum {
     SCAN_DVBT,
     SCAN_MAX,
 } FrontendScan;
@@ -125,6 +138,12 @@
     vector<FrontendStatus> expectTuneStatuses;
 };
 
+struct LnbConfig {
+    LnbVoltage voltage;
+    LnbTone tone;
+    LnbPosition position;
+};
+
 struct ChannelConfig {
     int32_t frontendId;
     int32_t channelId;
@@ -148,6 +167,8 @@
 
 static FrontendConfig frontendArray[FILTER_MAX];
 static FrontendConfig frontendScanArray[SCAN_MAX];
+static LnbConfig lnbArray[LNB_MAX];
+static vector<uint8_t> diseqcMsgArray[DISEQC_MAX];
 static ChannelConfig channelArray[FRONTEND_MAX];
 static FilterConfig filterArray[FILTER_MAX];
 static DemuxFilterType filterLinkageTypes[LINKAGE_DIR][FILTER_MAIN_TYPE_BIT_COUNT];
@@ -198,6 +219,18 @@
     });
 };
 
+/** Configuration array for the Lnb test */
+inline void initLnbConfig() {
+    lnbArray[LNB0].voltage = LnbVoltage::VOLTAGE_12V;
+    lnbArray[LNB0].tone = LnbTone::NONE;
+    lnbArray[LNB0].position = LnbPosition::UNDEFINED;
+};
+
+/** Diseqc messages array for the Lnb test */
+inline void initDiseqcMsg() {
+    diseqcMsgArray[DISEQC_POWER_ON] = {0xE, 0x0, 0x0, 0x0, 0x0, 0x3};
+};
+
 /** Configuration array for the filter test */
 inline void initFilterConfig() {
     // TS VIDEO filter setting for default implementation testing