Merge "Implement missing broadcastradio 1.1 VTS tests." into oc-mr1-dev
diff --git a/broadcastradio/1.1/default/Tuner.cpp b/broadcastradio/1.1/default/Tuner.cpp
index 1e6b9da..aacd523 100644
--- a/broadcastradio/1.1/default/Tuner.cpp
+++ b/broadcastradio/1.1/default/Tuner.cpp
@@ -144,6 +144,7 @@
         mCallback->tuneComplete(Result::OK, mCurrentProgramInfo.base);
     } else {
         mCallback1_1->tuneComplete_1_1(Result::OK, mCurrentProgramInfo.selector);
+        mCallback1_1->currentProgramInfoChanged();
     }
 }
 
@@ -214,8 +215,10 @@
         return Result::NOT_INITIALIZED;
     }
 
-    ALOGW_IF(!mIsAmfmConfigSet, "AM/FM config not set");
-    if (!mIsAmfmConfigSet) return Result::INVALID_STATE;
+    if (!mIsAmfmConfigSet) {
+        ALOGW("AM/FM config not set");
+        return Result::INVALID_STATE;
+    }
     mIsTuneCompleted = false;
 
     auto task = [this, direction]() {
@@ -256,14 +259,26 @@
     lock_guard<mutex> lk(mMut);
     if (mIsClosed) return Result::NOT_INITIALIZED;
 
-    if (utils::isAmFm(utils::getType(mCurrentProgram))) {
-        ALOGW_IF(!mIsAmfmConfigSet, "AM/FM config not set");
-        if (!mIsAmfmConfigSet) return Result::INVALID_STATE;
+    // checking if ProgramSelector is valid
+    auto programType = utils::getType(sel);
+    if (utils::isAmFm(programType)) {
+        if (!mIsAmfmConfigSet) {
+            ALOGW("AM/FM config not set");
+            return Result::INVALID_STATE;
+        }
 
         auto freq = utils::getId(sel, IdentifierType::AMFM_FREQUENCY);
         if (freq < mAmfmConfig.lowerLimit || freq > mAmfmConfig.upperLimit) {
             return Result::INVALID_ARGUMENTS;
         }
+    } else if (programType == ProgramType::DAB) {
+        if (!utils::hasId(sel, IdentifierType::DAB_SIDECC)) return Result::INVALID_ARGUMENTS;
+    } else if (programType == ProgramType::DRMO) {
+        if (!utils::hasId(sel, IdentifierType::DRMO_SERVICE_ID)) return Result::INVALID_ARGUMENTS;
+    } else if (programType == ProgramType::SXM) {
+        if (!utils::hasId(sel, IdentifierType::SXM_SERVICE_ID)) return Result::INVALID_ARGUMENTS;
+    } else {
+        return Result::INVALID_ARGUMENTS;
     }
 
     mIsTuneCompleted = false;
diff --git a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
index 41cea27..9143c41 100644
--- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
+++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
@@ -62,8 +62,17 @@
 static constexpr auto kConfigTimeout = 10s;
 static constexpr auto kConnectModuleTimeout = 1s;
 static constexpr auto kTuneTimeout = 30s;
+static constexpr auto kEventPropagationTimeout = 1s;
 static constexpr auto kFullScanTimeout = 1min;
 
+static constexpr ProgramType kStandardProgramTypes[] = {
+    ProgramType::AM,  ProgramType::FM,   ProgramType::AM_HD, ProgramType::FM_HD,
+    ProgramType::DAB, ProgramType::DRMO, ProgramType::SXM};
+
+static constexpr IdentifierType kVendorPrimartIds[] = {
+    IdentifierType::VENDOR1_PRIMARY, IdentifierType::VENDOR2_PRIMARY,
+    IdentifierType::VENDOR3_PRIMARY, IdentifierType::VENDOR4_PRIMARY};
+
 static void printSkipped(std::string msg) {
     std::cout << "[  SKIPPED ] " << msg << std::endl;
 }
@@ -84,7 +93,7 @@
     MOCK_METHOD1(backgroundScanAvailable, Return<void>(bool));
     MOCK_TIMEOUT_METHOD1(backgroundScanComplete, Return<void>(ProgramListResult));
     MOCK_METHOD0(programListChanged, Return<void>());
-    MOCK_METHOD0(currentProgramInfoChanged, Return<void>());
+    MOCK_TIMEOUT_METHOD0(currentProgramInfoChanged, Return<void>());
 };
 
 class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
@@ -315,7 +324,8 @@
  *  - getProgramList either succeeds or returns NOT_STARTED/NOT_READY status;
  *  - if the program list is NOT_STARTED, startBackgroundScan makes it completed
  *    within a full scan timeout and the next getProgramList call succeeds;
- *  - if the program list is not empty, tuneByProgramSelector call succeeds.
+ *  - if the program list is not empty, tuneByProgramSelector call succeeds;
+ *  - getProgramInformation_1_1 returns the same selector as returned in tuneComplete_1_1 call.
  */
 TEST_P(BroadcastRadioHalTest, TuneFromProgramList) {
     if (skipped) return;
@@ -340,12 +350,70 @@
     EXPECT_CALL(*mCallback, tuneComplete(_, _)).Times(0);
     EXPECT_TIMEOUT_CALL(*mCallback, tuneComplete_1_1, Result::OK, _)
         .WillOnce(DoAll(SaveArg<1>(&selCb), testing::Return(ByMove(Void()))));
+    EXPECT_TIMEOUT_CALL(*mCallback, currentProgramInfoChanged);
     auto tuneResult = mTuner->tuneByProgramSelector(firstProgram.selector);
     ASSERT_EQ(Result::OK, tuneResult);
     EXPECT_TIMEOUT_CALL_WAIT(*mCallback, tuneComplete_1_1, kTuneTimeout);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, currentProgramInfoChanged, kEventPropagationTimeout);
     EXPECT_EQ(firstProgram.selector.primaryId, selCb.primaryId);
+
+    bool called = false;
+    auto getResult = mTuner->getProgramInformation_1_1([&](Result result, ProgramInfo info) {
+        called = true;
+        EXPECT_EQ(Result::OK, result);
+        EXPECT_EQ(selCb, info.selector);
+    });
+    ASSERT_TRUE(getResult.isOk());
+    ASSERT_TRUE(called);
 }
 
+/**
+ * Test that primary vendor identifier isn't used for standard program types.
+ *
+ * Verifies that:
+ *  - tuneByProgramSelector fails when VENDORn_PRIMARY is set as a primary
+ *    identifier for program types other than VENDORn.
+ */
+TEST_P(BroadcastRadioHalTest, TuneFailsForPrimaryVendor) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    for (auto ptype : kStandardProgramTypes) {
+        ALOGD("Checking %s...", toString(ptype).c_str());
+        for (auto idtype : kVendorPrimartIds) {
+            ALOGD("...with %s", toString(idtype).c_str());
+            ProgramSelector sel = {};
+            sel.programType = static_cast<uint32_t>(ptype);
+            sel.primaryId.type = static_cast<uint32_t>(idtype);
+
+            auto tuneResult = mTuner->tuneByProgramSelector(sel);
+            ASSERT_NE(Result::OK, tuneResult);
+        }
+    }
+}
+
+/**
+ * Test that tune with unknown program type fails.
+ *
+ * Verifies that:
+ *  - tuneByProgramSelector fails with INVALID_ARGUMENT when unknown program type is passed.
+ */
+TEST_P(BroadcastRadioHalTest, TuneFailsForUnknownProgram) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    // Program type is 1-based, so 0 will be always invalid.
+    ProgramSelector sel = {};
+    auto tuneResult = mTuner->tuneByProgramSelector(sel);
+    ASSERT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
+}
+
+/**
+ * Test cancelling announcement.
+ *
+ * Verifies that:
+ *  - cancelAnnouncement succeeds either when there is an announcement or there is none.
+ */
 TEST_P(BroadcastRadioHalTest, CancelAnnouncement) {
     if (skipped) return;
     ASSERT_TRUE(openTuner());
@@ -358,7 +426,7 @@
  * Test getImage call with invalid image ID.
  *
  * Verifies that:
- * - getImage call handles argument 0 gracefully
+ * - getImage call handles argument 0 gracefully.
  */
 TEST_P(BroadcastRadioHalTest, GetNoImage) {
     if (skipped) return;
@@ -375,8 +443,8 @@
  * Test proper image format in metadata.
  *
  * Verifies that:
- * - all images in metadata are provided out-of-band (by id, not as a binary blob)
- * - images are available for getImage call
+ * - all images in metadata are provided out-of-band (by id, not as a binary blob);
+ * - images are available for getImage call.
  */
 TEST_P(BroadcastRadioHalTest, OobImagesOnly) {
     if (skipped) return;
@@ -420,7 +488,7 @@
  * Test AnalogForced switch.
  *
  * Verifies that:
- * - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same
+ * - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same.
  */
 TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
     if (skipped) return;
diff --git a/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
index fa1114f..b0ce088 100644
--- a/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
+++ b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
@@ -44,6 +44,14 @@
     return ret;
 
 /**
+ * Gmock MOCK_METHOD0 timeout-capable extension.
+ */
+#define MOCK_TIMEOUT_METHOD0(Method, ...)       \
+    MOCK_METHOD0(egmock_##Method, __VA_ARGS__); \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);         \
+    virtual GMOCK_RESULT_(, __VA_ARGS__) Method() { EGMOCK_TIMEOUT_METHOD_BODY_(Method); }
+
+/**
  * Gmock MOCK_METHOD1 timeout-capable extension.
  */
 #define MOCK_TIMEOUT_METHOD1(Method, ...)                                                 \