Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81ccaed5 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk Committed by Android (Google) Code Review
Browse files

Merge "Fix remaining instrumentation tests."

parents 8ce84699 db902860
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -112,6 +112,12 @@ Return<void> BroadcastRadio::getDabRegionConfig(getDabRegionConfig_cb _hidl_cb)
Return<void> BroadcastRadio::openSession(const sp<ITunerCallback>& callback,
                                         openSession_cb _hidl_cb) {
    ALOGV("%s", __func__);

    /* For the needs of default implementation it's fine to instantiate new session object
     * out of the lock scope. If your implementation needs it, use reentrant lock.
     */
    sp<TunerSession> newSession = new TunerSession(*this, callback);

    lock_guard<mutex> lk(mMut);

    auto oldSession = mSession.promote();
@@ -121,7 +127,6 @@ Return<void> BroadcastRadio::openSession(const sp<ITunerCallback>& callback,
        mSession = nullptr;
    }

    sp<TunerSession> newSession = new TunerSession(*this, callback);
    mSession = newSession;

    _hidl_cb(Result::OK, newSession);
+30 −5
Original line number Diff line number Diff line
@@ -50,7 +50,12 @@ static constexpr auto list = 1s;
}  // namespace delay

TunerSession::TunerSession(BroadcastRadio& module, const sp<ITunerCallback>& callback)
    : mCallback(callback), mModule(module) {}
    : mCallback(callback), mModule(module) {
    auto&& ranges = module.getAmFmConfig().ranges;
    if (ranges.size() > 0) {
        tuneInternalLocked(utils::make_selector_amfm(ranges[0].lowerBound));
    }
}

// makes ProgramInfo that points to no program
static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
@@ -63,6 +68,8 @@ static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
}

void TunerSession::tuneInternalLocked(const ProgramSelector& sel) {
    ALOGV("%s(%s)", __func__, toString(sel).c_str());

    VirtualProgram virtualProgram;
    ProgramInfo programInfo;
    if (virtualRadio().getProgram(sel, virtualProgram)) {
@@ -100,6 +107,8 @@ Return<Result> TunerSession::tune(const ProgramSelector& sel) {
        return Result::INVALID_ARGUMENTS;
    }

    cancelLocked();

    mIsTuneCompleted = false;
    auto task = [this, sel]() {
        lock_guard<mutex> lk(mMut);
@@ -115,6 +124,8 @@ Return<Result> TunerSession::scan(bool directionUp, bool /* skipSubChannel */) {
    lock_guard<mutex> lk(mMut);
    if (mIsClosed) return Result::INVALID_STATE;

    cancelLocked();

    auto list = virtualRadio().getProgramList();

    if (list.empty()) {
@@ -166,13 +177,13 @@ Return<Result> TunerSession::step(bool directionUp) {
    lock_guard<mutex> lk(mMut);
    if (mIsClosed) return Result::INVALID_STATE;

    cancelLocked();

    if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) {
        ALOGE("Can't step in anything else than AM/FM");
        return Result::NOT_SUPPORTED;
    }

    mIsTuneCompleted = false;

    auto stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
    auto range = getAmFmRangeLocked();
    if (!range) {
@@ -188,6 +199,7 @@ Return<Result> TunerSession::step(bool directionUp) {
    if (stepTo > range->upperBound) stepTo = range->lowerBound;
    if (stepTo < range->lowerBound) stepTo = range->upperBound;

    mIsTuneCompleted = false;
    auto task = [this, stepTo]() {
        ALOGI("Performing step to %s", std::to_string(stepTo).c_str());

@@ -200,12 +212,22 @@ Return<Result> TunerSession::step(bool directionUp) {
    return Result::OK;
}

void TunerSession::cancelLocked() {
    ALOGV("%s", __func__);

    mThread.cancelAll();
    if (utils::getType(mCurrentProgram.primaryId) != IdentifierType::INVALID) {
        mIsTuneCompleted = true;
    }
}

Return<void> TunerSession::cancel() {
    ALOGV("%s", __func__);
    lock_guard<mutex> lk(mMut);
    if (mIsClosed) return {};

    mThread.cancelAll();
    cancelLocked();

    return {};
}

@@ -281,7 +303,10 @@ Return<void> TunerSession::close() {
}

std::optional<AmFmBandRange> TunerSession::getAmFmRangeLocked() const {
    if (!mIsTuneCompleted) return {};
    if (!mIsTuneCompleted) {
        ALOGW("tune operation in process");
        return {};
    }
    if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) return {};

    auto freq = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ struct TunerSession : public ITunerSession {
    bool mIsTuneCompleted = false;
    ProgramSelector mCurrentProgram = {};

    void cancelLocked();
    void tuneInternalLocked(const ProgramSelector& sel);
    const VirtualRadio& virtualRadio() const;
    const BroadcastRadio& module() const;
+33 −2
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */

#define LOG_TAG "BcRadio.vts"
#define LOG_NDEBUG 0
#define EGMOCK_VERBOSE 1

#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
@@ -113,7 +115,15 @@ static void printSkipped(std::string msg) {
    std::cout << "[  SKIPPED ] " << 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);
}
@@ -362,9 +372,19 @@ TEST_F(BroadcastRadioHalTest, FmTune) {
    uint64_t freq = 100100;  // 100.1 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(100ms);

    // try tuning
    ProgramInfo infoCb = {};
    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _)
    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged,
                        InfoHasId(utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq)))
        .Times(AnyNumber())
        .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
    auto result = mSession->tune(sel);
@@ -379,6 +399,8 @@ TEST_F(BroadcastRadioHalTest, FmTune) {
    EXPECT_EQ(Result::OK, result);
    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);

    ALOGD("current program info: %s", toString(infoCb).c_str());

    // 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));
@@ -442,6 +464,9 @@ TEST_F(BroadcastRadioHalTest, TuneFailsWithEmpty) {
TEST_F(BroadcastRadioHalTest, Scan) {
    ASSERT_TRUE(openSession());

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

    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _);
    auto result = mSession->scan(true /* up */, true /* skip subchannel */);
    EXPECT_EQ(Result::OK, result);
@@ -464,9 +489,15 @@ TEST_F(BroadcastRadioHalTest, Scan) {
TEST_F(BroadcastRadioHalTest, Step) {
    ASSERT_TRUE(openSession());

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

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

+21 −3
Original line number Diff line number Diff line
@@ -13,12 +13,27 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_VTS_MOCK_TIMEOUT
#define ANDROID_HARDWARE_BROADCASTRADIO_VTS_MOCK_TIMEOUT

#include <gmock/gmock.h>
#include <thread>

#ifndef EGMOCK_VERBOSE
#define EGMOCK_VERBOSE 0
#endif

/**
 * Print log message.
 *
 * INTERNAL IMPLEMENTATION - don't use in user code.
 */
#if EGMOCK_VERBOSE
#define EGMOCK_LOG_(...) ALOGV("egmock: " __VA_ARGS__)
#else
#define EGMOCK_LOG_(...)
#endif

/**
 * Common helper objects for gmock timeout extension.
 *
@@ -61,6 +76,7 @@ inline void EGMockFlippedComma_(std::function<void()> returned, std::function<vo
    auto invokeMock = [&]() { return egmock_##Method(__VA_ARGS__); }; \
    auto notify = [&]() {                                             \
        std::lock_guard<std::mutex> lk(egmock_mut_##Method);          \
        EGMOCK_LOG_(#Method " called");                               \
        egmock_called_##Method = true;                                \
        egmock_cond_##Method.notify_all();                            \
    };                                                                \
@@ -105,6 +121,7 @@ inline void EGMockFlippedComma_(std::function<void()> returned, std::function<vo
 *     EXPECT_TIMEOUT_CALL(account, charge, 100, Currency::USD);
 */
#define EXPECT_TIMEOUT_CALL(obj, Method, ...) \
    EGMOCK_LOG_(#Method " expected to call"); \
    (obj).egmock_called_##Method = false;     \
    EXPECT_CALL(obj, egmock_##Method(__VA_ARGS__))

@@ -124,6 +141,7 @@ inline void EGMockFlippedComma_(std::function<void()> returned, std::function<vo
 */
#define EXPECT_TIMEOUT_CALL_WAIT(obj, Method, timeout)                      \
    {                                                                       \
        EGMOCK_LOG_("waiting for " #Method " call");                        \
        std::unique_lock<std::mutex> lk((obj).egmock_mut_##Method);         \
        if (!(obj).egmock_called_##Method) {                                \
            auto status = (obj).egmock_cond_##Method.wait_for(lk, timeout); \
@@ -131,4 +149,4 @@ inline void EGMockFlippedComma_(std::function<void()> returned, std::function<vo
        }                                                                   \
    }

#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
#endif  // ANDROID_HARDWARE_BROADCASTRADIO_VTS_MOCK_TIMEOUT