/*
 * Copyright (C) 2017 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 EGMOCK_VERBOSE 1

#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android/hardware/broadcastradio/2.0/IBroadcastRadio.h>
#include <android/hardware/broadcastradio/2.0/ITunerCallback.h>
#include <android/hardware/broadcastradio/2.0/ITunerSession.h>
#include <android/hardware/broadcastradio/2.0/types.h>
#include <broadcastradio-utils-2x/Utils.h>
#include <broadcastradio-vts-utils/call-barrier.h>
#include <broadcastradio-vts-utils/mock-timeout.h>
#include <broadcastradio-vts-utils/pointer-utils.h>
#include <cutils/bitops.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>

#include <chrono>
#include <optional>
#include <regex>

namespace android {
namespace hardware {
namespace broadcastradio {
namespace V2_0 {
namespace vts {

using namespace std::chrono_literals;

using std::unordered_set;
using std::vector;
using testing::_;
using testing::AnyNumber;
using testing::ByMove;
using testing::DoAll;
using testing::Invoke;
using testing::SaveArg;

using broadcastradio::vts::CallBarrier;
using broadcastradio::vts::clearAndWait;
using utils::make_identifier;
using utils::make_selector_amfm;

namespace timeout {

static constexpr auto tune = 30s;
static constexpr auto programListScan = 5min;

}  // namespace timeout

static constexpr auto gTuneWorkaround = 200ms;

static const ConfigFlag gConfigFlagValues[] = {
    ConfigFlag::FORCE_MONO,
    ConfigFlag::FORCE_ANALOG,
    ConfigFlag::FORCE_DIGITAL,
    ConfigFlag::RDS_AF,
    ConfigFlag::RDS_REG,
    ConfigFlag::DAB_DAB_LINKING,
    ConfigFlag::DAB_FM_LINKING,
    ConfigFlag::DAB_DAB_SOFT_LINKING,
    ConfigFlag::DAB_FM_SOFT_LINKING,
};

class TunerCallbackMock : public ITunerCallback {
   public:
    TunerCallbackMock();

    MOCK_METHOD2(onTuneFailed, Return<void>(Result, const ProgramSelector&));
    MOCK_TIMEOUT_METHOD1(onCurrentProgramInfoChanged_, Return<void>(const ProgramInfo&));
    virtual Return<void> onCurrentProgramInfoChanged(const ProgramInfo& info);
    Return<void> onProgramListUpdated(const ProgramListChunk& chunk);
    MOCK_METHOD1(onAntennaStateChange, Return<void>(bool connected));
    MOCK_METHOD1(onParametersUpdated, Return<void>(const hidl_vec<VendorKeyValue>& parameters));

    MOCK_TIMEOUT_METHOD0(onProgramListReady, void());

    std::mutex mLock;
    utils::ProgramInfoSet mProgramList;
};

struct AnnouncementListenerMock : public IAnnouncementListener {
    MOCK_METHOD1(onListUpdated, Return<void>(const hidl_vec<Announcement>&));
};

class BroadcastRadioHalTest : public ::testing::TestWithParam<std::string> {
  protected:
    virtual void SetUp() override;
    virtual void TearDown() override;

    bool openSession();
    bool getAmFmRegionConfig(bool full, AmFmRegionConfig* config);
    std::optional<utils::ProgramInfoSet> getProgramList();

    sp<IBroadcastRadio> mModule;
    Properties mProperties;
    sp<ITunerSession> mSession;
    sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
};

static void printSkipped(std::string msg) {
    const auto testInfo = testing::UnitTest::GetInstance()->current_test_info();
    std::cout << "[  SKIPPED ] " << testInfo->test_case_name() << "." << testInfo->name()
              << std::endl;
    std::cout << msg << std::endl;
}

MATCHER_P(InfoHasId, id,
          std::string(negation ? "does not contain" : "contains") + " " + toString(id)) {
    auto ids = utils::getAllIds(arg.selector, utils::getType(id));
    return ids.end() != find(ids.begin(), ids.end(), id.value);
}

TunerCallbackMock::TunerCallbackMock() {
    EXPECT_TIMEOUT_CALL(*this, onCurrentProgramInfoChanged_, _).Times(AnyNumber());

    // we expect the antenna is connected through the whole test
    EXPECT_CALL(*this, onAntennaStateChange(false)).Times(0);
}

Return<void> TunerCallbackMock::onCurrentProgramInfoChanged(const ProgramInfo& info) {
    for (auto&& id : info.selector) {
        EXPECT_NE(IdentifierType::INVALID, utils::getType(id));
    }

    auto logically = utils::getType(info.logicallyTunedTo);
    /* This field is required for currently tuned program and should be INVALID
     * for entries from the program list.
     */
    EXPECT_TRUE(
        logically == IdentifierType::AMFM_FREQUENCY || logically == IdentifierType::RDS_PI ||
        logically == IdentifierType::HD_STATION_ID_EXT ||
        logically == IdentifierType::DAB_SID_EXT || logically == IdentifierType::DRMO_SERVICE_ID ||
        logically == IdentifierType::SXM_SERVICE_ID ||
        (logically >= IdentifierType::VENDOR_START && logically <= IdentifierType::VENDOR_END) ||
        logically > IdentifierType::SXM_CHANNEL);

    auto physically = utils::getType(info.physicallyTunedTo);
    // ditto (see "logically" above)
    EXPECT_TRUE(
        physically == IdentifierType::AMFM_FREQUENCY ||
        physically == IdentifierType::DAB_ENSEMBLE ||
        physically == IdentifierType::DRMO_FREQUENCY || physically == IdentifierType::SXM_CHANNEL ||
        (physically >= IdentifierType::VENDOR_START && physically <= IdentifierType::VENDOR_END) ||
        physically > IdentifierType::SXM_CHANNEL);

    if (logically == IdentifierType::AMFM_FREQUENCY) {
        auto ps = utils::getMetadataString(info, MetadataKey::RDS_PS);
        if (ps.has_value()) {
            EXPECT_NE("", android::base::Trim(*ps))
                << "Don't use empty RDS_PS as an indicator of missing RSD PS data.";
        }
    }

    return onCurrentProgramInfoChanged_(info);
}

Return<void> TunerCallbackMock::onProgramListUpdated(const ProgramListChunk& chunk) {
    std::lock_guard<std::mutex> lk(mLock);

    updateProgramList(mProgramList, chunk);

    if (chunk.complete) onProgramListReady();

    return {};
}

void BroadcastRadioHalTest::SetUp() {
    EXPECT_EQ(nullptr, mModule.get()) << "Module is already open";

    // lookup HIDL service (radio module)
    mModule = IBroadcastRadio::getService(GetParam());
    ASSERT_NE(nullptr, mModule.get()) << "Couldn't find broadcast radio HAL implementation";

    // get module properties
    auto propResult = mModule->getProperties([&](const Properties& p) { mProperties = p; });
    ASSERT_TRUE(propResult.isOk());

    EXPECT_FALSE(mProperties.maker.empty());
    EXPECT_FALSE(mProperties.product.empty());
    EXPECT_GT(mProperties.supportedIdentifierTypes.size(), 0u);
}

void BroadcastRadioHalTest::TearDown() {
    mSession.clear();
    mModule.clear();
    clearAndWait(mCallback, 1s);
}

bool BroadcastRadioHalTest::openSession() {
    EXPECT_EQ(nullptr, mSession.get()) << "Session is already open";

    Result halResult = Result::UNKNOWN_ERROR;
    auto openCb = [&](Result result, const sp<ITunerSession>& session) {
        halResult = result;
        if (result != Result::OK) return;
        mSession = session;
    };
    auto hidlResult = mModule->openSession(mCallback, openCb);

    EXPECT_TRUE(hidlResult.isOk());
    EXPECT_EQ(Result::OK, halResult);
    EXPECT_NE(nullptr, mSession.get());

    return nullptr != mSession.get();
}

bool BroadcastRadioHalTest::getAmFmRegionConfig(bool full, AmFmRegionConfig* config) {
    auto halResult = Result::UNKNOWN_ERROR;
    auto cb = [&](Result result, AmFmRegionConfig configCb) {
        halResult = result;
        if (config) *config = configCb;
    };

    auto hidlResult = mModule->getAmFmRegionConfig(full, cb);
    EXPECT_TRUE(hidlResult.isOk());

    if (halResult == Result::NOT_SUPPORTED) return false;

    EXPECT_EQ(Result::OK, halResult);
    return halResult == Result::OK;
}

std::optional<utils::ProgramInfoSet> BroadcastRadioHalTest::getProgramList() {
    EXPECT_TIMEOUT_CALL(*mCallback, onProgramListReady).Times(AnyNumber());

    auto startResult = mSession->startProgramListUpdates({});
    if (startResult == Result::NOT_SUPPORTED) {
        printSkipped("Program list not supported");
        return std::nullopt;
    }
    EXPECT_EQ(Result::OK, startResult);
    if (startResult != Result::OK) return std::nullopt;

    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onProgramListReady, timeout::programListScan);

    auto stopResult = mSession->stopProgramListUpdates();
    EXPECT_TRUE(stopResult.isOk());

    return mCallback->mProgramList;
}

/**
 * Test session opening.
 *
 * Verifies that:
 *  - the method succeeds on a first and subsequent calls;
 *  - the method succeeds when called for the second time without
 *    closing previous session.
 */
TEST_P(BroadcastRadioHalTest, OpenSession) {
    // simply open session for the first time
    ASSERT_TRUE(openSession());

    // drop (without explicit close) and re-open the session
    mSession.clear();
    ASSERT_TRUE(openSession());

    // open the second session (the first one should be forcibly closed)
    auto secondSession = mSession;
    mSession.clear();
    ASSERT_TRUE(openSession());
}

static bool isValidAmFmFreq(uint64_t freq) {
    auto id = utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq);
    return utils::isValid(id);
}

static void validateRange(const AmFmBandRange& range) {
    EXPECT_TRUE(isValidAmFmFreq(range.lowerBound));
    EXPECT_TRUE(isValidAmFmFreq(range.upperBound));
    EXPECT_LT(range.lowerBound, range.upperBound);
    EXPECT_GT(range.spacing, 0u);
    EXPECT_EQ(0u, (range.upperBound - range.lowerBound) % range.spacing);
}

static bool supportsFM(const AmFmRegionConfig& config) {
    for (auto&& range : config.ranges) {
        if (utils::getBand(range.lowerBound) == utils::FrequencyBand::FM) return true;
    }
    return false;
}

/**
 * Test fetching AM/FM regional configuration.
 *
 * Verifies that:
 *  - AM/FM regional configuration is either set at startup or not supported at all by the hardware;
 *  - there is at least one AM/FM band configured;
 *  - FM Deemphasis and RDS are correctly configured for FM-capable radio;
 *  - all channel grids (frequency ranges and spacings) are valid;
 *  - seek spacing is a multiple of the manual spacing value.
 */
TEST_P(BroadcastRadioHalTest, GetAmFmRegionConfig) {
    AmFmRegionConfig config;
    bool supported = getAmFmRegionConfig(false, &config);
    if (!supported) {
        printSkipped("AM/FM not supported");
        return;
    }

    EXPECT_GT(config.ranges.size(), 0u);
    EXPECT_LE(popcountll(config.fmDeemphasis), 1);
    EXPECT_LE(popcountll(config.fmRds), 1);

    for (auto&& range : config.ranges) {
        validateRange(range);
        EXPECT_EQ(0u, range.scanSpacing % range.spacing);
        EXPECT_GE(range.scanSpacing, range.spacing);
    }

    if (supportsFM(config)) {
        EXPECT_EQ(popcountll(config.fmDeemphasis), 1);
    }
}

/**
 * Test fetching AM/FM regional capabilities.
 *
 * Verifies that:
 *  - AM/FM regional capabilities are either available or not supported at all by the hardware;
 *  - there is at least one AM/FM range supported;
 *  - there is at least one de-emphasis filter mode supported for FM-capable radio;
 *  - all channel grids (frequency ranges and spacings) are valid;
 *  - seek spacing is not set.
 */
TEST_P(BroadcastRadioHalTest, GetAmFmRegionConfigCapabilities) {
    AmFmRegionConfig config;
    bool supported = getAmFmRegionConfig(true, &config);
    if (!supported) {
        printSkipped("AM/FM not supported");
        return;
    }

    EXPECT_GT(config.ranges.size(), 0u);

    for (auto&& range : config.ranges) {
        validateRange(range);
        EXPECT_EQ(0u, range.scanSpacing);
    }

    if (supportsFM(config)) {
        EXPECT_GE(popcountll(config.fmDeemphasis), 1);
    }
}

/**
 * Test fetching DAB regional configuration.
 *
 * Verifies that:
 *  - DAB regional configuration is either set at startup or not supported at all by the hardware;
 *  - all channel labels match correct format;
 *  - all channel frequencies are in correct range.
 */
TEST_P(BroadcastRadioHalTest, GetDabRegionConfig) {
    Result halResult;
    hidl_vec<DabTableEntry> config;
    auto cb = [&](Result result, hidl_vec<DabTableEntry> configCb) {
        halResult = result;
        config = configCb;
    };
    auto hidlResult = mModule->getDabRegionConfig(cb);
    ASSERT_TRUE(hidlResult.isOk());

    if (halResult == Result::NOT_SUPPORTED) {
        printSkipped("DAB not supported");
        return;
    }
    ASSERT_EQ(Result::OK, halResult);

    std::regex re("^[A-Z0-9][A-Z0-9 ]{0,5}[A-Z0-9]$");
    // double-check correctness of the test
    ASSERT_TRUE(std::regex_match("5A", re));
    ASSERT_FALSE(std::regex_match("5a", re));
    ASSERT_FALSE(std::regex_match("1234ABCD", re));
    ASSERT_TRUE(std::regex_match("CN 12D", re));
    ASSERT_FALSE(std::regex_match(" 5A", re));

    for (auto&& entry : config) {
        EXPECT_TRUE(std::regex_match(std::string(entry.label), re));

        auto id = utils::make_identifier(IdentifierType::DAB_FREQUENCY, entry.frequency);
        EXPECT_TRUE(utils::isValid(id));
    }
}

/**
 * Test tuning with FM selector.
 *
 * Verifies that:
 *  - if AM/FM selector is not supported, the method returns NOT_SUPPORTED;
 *  - if it is supported, the method succeeds;
 *  - after a successful tune call, onCurrentProgramInfoChanged callback is
 *    invoked carrying a proper selector;
 *  - program changes exactly to what was requested.
 */
TEST_P(BroadcastRadioHalTest, FmTune) {
    ASSERT_TRUE(openSession());

    uint64_t freq = 90900;  // 90.9 FM
    auto sel = make_selector_amfm(freq);

    /* TODO(b/69958777): there is a race condition between tune() and onCurrentProgramInfoChanged
     * callback setting infoCb, because egmock cannot distinguish calls with different matchers
     * (there is one here and one in callback constructor).
     *
     * This sleep workaround will fix default implementation, but the real HW tests will still be
     * flaky. We probably need to implement egmock alternative based on actions.
     */
    std::this_thread::sleep_for(gTuneWorkaround);

    // try tuning
    ProgramInfo infoCb = {};
    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged_,
                        InfoHasId(utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq)))
            .Times(AnyNumber())
            .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))))
            .WillRepeatedly(testing::InvokeWithoutArgs([] { return Void(); }));
    auto result = mSession->tune(sel);

    // expect a failure if it's not supported
    if (!utils::isSupported(mProperties, sel)) {
        EXPECT_EQ(Result::NOT_SUPPORTED, result);
        return;
    }

    // expect a callback if it succeeds
    EXPECT_EQ(Result::OK, result);
    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged_, timeout::tune);

    LOG(DEBUG) << "current program info: " << toString(infoCb);

    // it should tune exactly to what was requested
    auto freqs = utils::getAllIds(infoCb.selector, IdentifierType::AMFM_FREQUENCY);
    EXPECT_NE(freqs.end(), find(freqs.begin(), freqs.end(), freq));
}

/**
 * Test tuning with invalid selectors.
 *
 * Verifies that:
 *  - if the selector is not supported, it's ignored;
 *  - if it is supported, an invalid value results with INVALID_ARGUMENTS;
 */
TEST_P(BroadcastRadioHalTest, TuneFailsWithInvalid) {
    ASSERT_TRUE(openSession());

    vector<ProgramIdentifier> invalid = {
        make_identifier(IdentifierType::AMFM_FREQUENCY, 0),
        make_identifier(IdentifierType::RDS_PI, 0x10000),
        make_identifier(IdentifierType::HD_STATION_ID_EXT, 0x100000000),
        make_identifier(IdentifierType::DAB_SID_EXT, 0),
        make_identifier(IdentifierType::DRMO_SERVICE_ID, 0x100000000),
        make_identifier(IdentifierType::SXM_SERVICE_ID, 0x100000000),
    };

    for (auto&& id : invalid) {
        ProgramSelector sel{id, {}};

        auto result = mSession->tune(sel);

        if (utils::isSupported(mProperties, sel)) {
            EXPECT_EQ(Result::INVALID_ARGUMENTS, result);
        } else {
            EXPECT_EQ(Result::NOT_SUPPORTED, result);
        }
    }
}

/**
 * Test tuning with DAB selector.
 *
 * Verifies that:
 *  - if DAB selector is not supported, the method returns NOT_SUPPORTED;
 *  - if it is supported, the method succeeds;
 *  - after a successful tune call, onCurrentProgramInfoChanged callback is
 *    invoked carrying a proper selector;
 *  - program changes exactly to what was requested.
 */
TEST_F(BroadcastRadioHalTest, DabTune) {
    ASSERT_TRUE(openSession());

    ProgramSelector sel = {};
    uint64_t freq = 178352;
    sel.primaryId = make_identifier(IdentifierType::DAB_FREQUENCY,freq);

    std::this_thread::sleep_for(gTuneWorkaround);

    // try tuning
    ProgramInfo infoCb = {};
    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged_,
                        InfoHasId(utils::make_identifier(IdentifierType::DAB_FREQUENCY, freq)))
        .Times(AnyNumber())
        .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
    auto result = mSession->tune(sel);

    // expect a failure if it's not supported
    if (!utils::isSupported(mProperties, sel)) {
        EXPECT_EQ(Result::NOT_SUPPORTED, result);
        return;
    }

    // expect a callback if it succeeds
    EXPECT_EQ(Result::OK, result);
    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged_, timeout::tune);

    LOG(DEBUG) << "current program info: " << toString(infoCb);

    // it should tune exactly to what was requested
    auto freqs = utils::getAllIds(infoCb.selector, IdentifierType::DAB_FREQUENCY);
    EXPECT_NE(freqs.end(), find(freqs.begin(), freqs.end(), freq));
}

/**
 * Test tuning with empty program selector.
 *
 * Verifies that:
 *  - tune fails with NOT_SUPPORTED when program selector is not initialized.
 */
TEST_P(BroadcastRadioHalTest, TuneFailsWithEmpty) {
    ASSERT_TRUE(openSession());

    // Program type is 1-based, so 0 will always be invalid.
    ProgramSelector sel = {};
    auto result = mSession->tune(sel);
    ASSERT_EQ(Result::NOT_SUPPORTED, result);
}

/**
 * Test seeking to next/prev station via ITunerSession::scan().
 *
 * Verifies that:
 *  - the method succeeds;
 *  - the program info is changed within timeout::tune;
 *  - works both directions and with or without skipping sub-channel.
 */
TEST_P(BroadcastRadioHalTest, Seek) {
    ASSERT_TRUE(openSession());

    // TODO(b/69958777): see FmTune workaround
    std::this_thread::sleep_for(gTuneWorkaround);

    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged_, _).Times(AnyNumber());
    auto result = mSession->scan(true /* up */, true /* skip subchannel */);

    if (result == Result::NOT_SUPPORTED) {
        printSkipped("seek not supported");
        return;
    }

    EXPECT_EQ(Result::OK, result);
    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged_, timeout::tune);

    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged_, _).Times(AnyNumber());
    result = mSession->scan(false /* down */, false /* don't skip subchannel */);
    EXPECT_EQ(Result::OK, result);
    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged_, timeout::tune);
}

/**
 * Test step operation.
 *
 * Verifies that:
 *  - the method succeeds or returns NOT_SUPPORTED;
 *  - the program info is changed within timeout::tune if the method succeeded;
 *  - works both directions.
 */
TEST_P(BroadcastRadioHalTest, Step) {
    ASSERT_TRUE(openSession());

    // TODO(b/69958777): see FmTune workaround
    std::this_thread::sleep_for(gTuneWorkaround);

    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged_, _).Times(AnyNumber());
    auto result = mSession->step(true /* up */);
    if (result == Result::NOT_SUPPORTED) {
        printSkipped("step not supported");
        return;
    }
    EXPECT_EQ(Result::OK, result);
    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged_, timeout::tune);

    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged_, _).Times(AnyNumber());
    result = mSession->step(false /* down */);
    EXPECT_EQ(Result::OK, result);
    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged_, timeout::tune);
}

/**
 * Test tune cancellation.
 *
 * Verifies that:
 *  - the method does not crash after being invoked multiple times.
 */
TEST_P(BroadcastRadioHalTest, Cancel) {
    ASSERT_TRUE(openSession());

    for (int i = 0; i < 10; i++) {
        auto result = mSession->scan(true /* up */, true /* skip subchannel */);

        if (result == Result::NOT_SUPPORTED) {
            printSkipped("cancel is skipped because of seek not supported");
            return;
        }

        ASSERT_EQ(Result::OK, result);

        auto cancelResult = mSession->cancel();
        ASSERT_TRUE(cancelResult.isOk());
    }
}

/**
 * Test IBroadcastRadio::get|setParameters() methods called with no parameters.
 *
 * Verifies that:
 *  - callback is called for empty parameters set.
 */
TEST_P(BroadcastRadioHalTest, NoParameters) {
    ASSERT_TRUE(openSession());

    hidl_vec<VendorKeyValue> halResults = {};
    bool wasCalled = false;
    auto cb = [&](hidl_vec<VendorKeyValue> results) {
        wasCalled = true;
        halResults = results;
    };

    auto hidlResult = mSession->setParameters({}, cb);
    ASSERT_TRUE(hidlResult.isOk());
    ASSERT_TRUE(wasCalled);
    ASSERT_EQ(0u, halResults.size());

    wasCalled = false;
    hidlResult = mSession->getParameters({}, cb);
    ASSERT_TRUE(hidlResult.isOk());
    ASSERT_TRUE(wasCalled);
    ASSERT_EQ(0u, halResults.size());
}

/**
 * Test IBroadcastRadio::get|setParameters() methods called with unknown parameters.
 *
 * Verifies that:
 *  - unknown parameters are ignored;
 *  - callback is called also for empty results set.
 */
TEST_P(BroadcastRadioHalTest, UnknownParameters) {
    ASSERT_TRUE(openSession());

    hidl_vec<VendorKeyValue> halResults = {};
    bool wasCalled = false;
    auto cb = [&](hidl_vec<VendorKeyValue> results) {
        wasCalled = true;
        halResults = results;
    };

    auto hidlResult = mSession->setParameters({{"com.google.unknown", "dummy"}}, cb);
    ASSERT_TRUE(hidlResult.isOk());
    ASSERT_TRUE(wasCalled);
    ASSERT_EQ(0u, halResults.size());

    wasCalled = false;
    hidlResult = mSession->getParameters({{"com.google.unknown*", "dummy"}}, cb);
    ASSERT_TRUE(hidlResult.isOk());
    ASSERT_TRUE(wasCalled);
    ASSERT_EQ(0u, halResults.size());
}

/**
 * Test session closing.
 *
 * Verifies that:
 *  - the method does not crash after being invoked multiple times.
 */
TEST_P(BroadcastRadioHalTest, Close) {
    ASSERT_TRUE(openSession());

    for (int i = 0; i < 10; i++) {
        auto cancelResult = mSession->close();
        ASSERT_TRUE(cancelResult.isOk());
    }
}

/**
 * Test geting image of invalid ID.
 *
 * Verifies that:
 * - getImage call handles argument 0 gracefully.
 */
TEST_P(BroadcastRadioHalTest, GetNoImage) {
    size_t len = 0;
    auto result = mModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });

    ASSERT_TRUE(result.isOk());
    ASSERT_EQ(0u, len);
}

/**
 * Test getting config flags.
 *
 * Verifies that:
 * - isConfigFlagSet either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
 * - call success or failure is consistent with setConfigFlag.
 */
TEST_P(BroadcastRadioHalTest, FetchConfigFlags) {
    ASSERT_TRUE(openSession());

    for (auto flag : gConfigFlagValues) {
        auto halResult = Result::UNKNOWN_ERROR;
        auto cb = [&](Result result, bool) { halResult = result; };
        auto hidlResult = mSession->isConfigFlagSet(flag, cb);
        EXPECT_TRUE(hidlResult.isOk());

        if (halResult != Result::NOT_SUPPORTED && halResult != Result::INVALID_STATE) {
            ASSERT_EQ(Result::OK, halResult);
        }

        // set must fail or succeed the same way as get
        auto setResult = mSession->setConfigFlag(flag, false);
        EXPECT_EQ(halResult, setResult);
        setResult = mSession->setConfigFlag(flag, true);
        EXPECT_EQ(halResult, setResult);
    }
}

/**
 * Test setting config flags.
 *
 * Verifies that:
 * - setConfigFlag either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
 * - isConfigFlagSet reflects the state requested immediately after the set call.
 */
TEST_P(BroadcastRadioHalTest, SetConfigFlags) {
    ASSERT_TRUE(openSession());

    auto get = [&](ConfigFlag flag) {
        auto halResult = Result::UNKNOWN_ERROR;
        bool gotValue = false;
        auto cb = [&](Result result, bool value) {
            halResult = result;
            gotValue = value;
        };
        auto hidlResult = mSession->isConfigFlagSet(flag, cb);
        EXPECT_TRUE(hidlResult.isOk());
        EXPECT_EQ(Result::OK, halResult);
        return gotValue;
    };

    for (auto flag : gConfigFlagValues) {
        auto result = mSession->setConfigFlag(flag, false);
        if (result == Result::NOT_SUPPORTED || result == Result::INVALID_STATE) {
            // setting to true must result in the same error as false
            auto secondResult = mSession->setConfigFlag(flag, true);
            EXPECT_EQ(result, secondResult);
            continue;
        }
        ASSERT_EQ(Result::OK, result);

        // verify false is set
        auto value = get(flag);
        EXPECT_FALSE(value);

        // try setting true this time
        result = mSession->setConfigFlag(flag, true);
        ASSERT_EQ(Result::OK, result);
        value = get(flag);
        EXPECT_TRUE(value);

        // false again
        result = mSession->setConfigFlag(flag, false);
        ASSERT_EQ(Result::OK, result);
        value = get(flag);
        EXPECT_FALSE(value);
    }
}

/**
 * Test getting program list.
 *
 * Verifies that:
 * - startProgramListUpdates either succeeds or returns NOT_SUPPORTED;
 * - the complete list is fetched within timeout::programListScan;
 * - stopProgramListUpdates does not crash.
 */
TEST_P(BroadcastRadioHalTest, GetProgramList) {
    ASSERT_TRUE(openSession());

    getProgramList();
}

/**
 * Test HD_STATION_NAME correctness.
 *
 * Verifies that if a program on the list contains HD_STATION_NAME identifier:
 *  - the program provides station name in its metadata;
 *  - the identifier matches the name;
 *  - there is only one identifier of that type.
 */
TEST_P(BroadcastRadioHalTest, HdRadioStationNameId) {
    ASSERT_TRUE(openSession());

    auto list = getProgramList();
    if (!list) return;

    for (auto&& program : *list) {
        auto nameIds = utils::getAllIds(program.selector, IdentifierType::HD_STATION_NAME);
        EXPECT_LE(nameIds.size(), 1u);
        if (nameIds.size() == 0) continue;

        auto name = utils::getMetadataString(program, MetadataKey::PROGRAM_NAME);
        if (!name) name = utils::getMetadataString(program, MetadataKey::RDS_PS);
        ASSERT_TRUE(name.has_value());

        auto expectedId = utils::make_hdradio_station_name(*name);
        EXPECT_EQ(expectedId.value, nameIds[0]);
    }
}

/**
 * Test announcement listener registration.
 *
 * Verifies that:
 *  - registerAnnouncementListener either succeeds or returns NOT_SUPPORTED;
 *  - if it succeeds, it returns a valid close handle (which is a nullptr otherwise);
 *  - closing handle does not crash.
 */
TEST_P(BroadcastRadioHalTest, AnnouncementListenerRegistration) {
    sp<AnnouncementListenerMock> listener = new AnnouncementListenerMock();

    Result halResult = Result::UNKNOWN_ERROR;
    sp<ICloseHandle> closeHandle = nullptr;
    auto cb = [&](Result result, const sp<ICloseHandle>& closeHandle_) {
        halResult = result;
        closeHandle = closeHandle_;
    };

    auto hidlResult =
        mModule->registerAnnouncementListener({AnnouncementType::EMERGENCY}, listener, cb);
    ASSERT_TRUE(hidlResult.isOk());

    if (halResult == Result::NOT_SUPPORTED) {
        ASSERT_EQ(nullptr, closeHandle.get());
        printSkipped("Announcements not supported");
        return;
    }

    ASSERT_EQ(Result::OK, halResult);
    ASSERT_NE(nullptr, closeHandle.get());

    closeHandle->close();
}

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BroadcastRadioHalTest);
INSTANTIATE_TEST_SUITE_P(
        PerInstance, BroadcastRadioHalTest,
        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBroadcastRadio::descriptor)),
        android::hardware::PrintInstanceNameToString);

}  // namespace vts
}  // namespace V2_0
}  // namespace broadcastradio
}  // namespace hardware
}  // namespace android

int main(int argc, char** argv) {
    android::base::SetDefaultTag("BcRadio.vts");
    android::base::SetMinimumLogSeverity(android::base::VERBOSE);
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
