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

Commit d9168905 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add tuner callback for default bcradio HAL" into main

parents b28ec8ac b61ee9eb
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -14,10 +14,13 @@
 * limitations under the License.
 */

#include "MockBroadcastRadioCallback.h"

#include <BroadcastRadio.h>
#include <VirtualRadio.h>
#include <broadcastradio-utils-aidl/Utils.h>

#include <android-base/logging.h>
#include <gtest/gtest.h>

namespace aidl::android::hardware::broadcastradio {
@@ -74,10 +77,19 @@ const VirtualRadio& getAmFmMockTestRadio() {
class DefaultBroadcastRadioHalTest : public testing::Test {
  public:
    void SetUp() override {
        ::android::base::SetDefaultTag("BcRadioAidlDef.test");
        const VirtualRadio& amFmRadioMockTest = getAmFmMockTestRadio();
        mBroadcastRadioHal = ::ndk::SharedRefBase::make<BroadcastRadio>(amFmRadioMockTest);
        mTunerCallback = ndk::SharedRefBase::make<MockBroadcastRadioCallback>();
    }

    void TearDown() override {
        mBroadcastRadioHal->unsetTunerCallback();
        EXPECT_FALSE(mTunerCallback->isTunerFailed());
    }

    std::shared_ptr<BroadcastRadio> mBroadcastRadioHal;
    std::shared_ptr<MockBroadcastRadioCallback> mTunerCallback;
};

TEST_F(DefaultBroadcastRadioHalTest, GetAmFmRegionConfig) {
@@ -136,4 +148,24 @@ TEST_F(DefaultBroadcastRadioHalTest, GetProperties) {
    }
}

TEST_F(DefaultBroadcastRadioHalTest, SetTunerCallback) {
    auto halResult = mBroadcastRadioHal->setTunerCallback(mTunerCallback);

    ASSERT_TRUE(halResult.isOk());
}

TEST_F(DefaultBroadcastRadioHalTest, SetTunerCallbackWithNull) {
    auto halResult = mBroadcastRadioHal->setTunerCallback(nullptr);

    ASSERT_EQ(halResult.getServiceSpecificError(), utils::resultToInt(Result::INVALID_ARGUMENTS));
}

TEST_F(DefaultBroadcastRadioHalTest, UnsetTunerCallbackWithNull) {
    ASSERT_TRUE(mBroadcastRadioHal->setTunerCallback(mTunerCallback).isOk());

    auto halResult = mBroadcastRadioHal->unsetTunerCallback();

    ASSERT_TRUE(halResult.isOk());
}

}  // namespace aidl::android::hardware::broadcastradio
+93 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 "MockBroadcastRadioCallback.h"

#include <android-base/logging.h>

namespace aidl::android::hardware::broadcastradio {

namespace {
using std::vector;
}

MockBroadcastRadioCallback::MockBroadcastRadioCallback() {
    mAntennaConnectionState = true;
}

ScopedAStatus MockBroadcastRadioCallback::onTuneFailed(Result result,
                                                       const ProgramSelector& selector) {
    LOG(DEBUG) << "onTuneFailed with result with " << selector.toString().c_str();
    if (result != Result::CANCELED) {
        std::lock_guard<std::mutex> lk(mLock);
        tunerFailed = true;
    }
    return ndk::ScopedAStatus::ok();
}

ScopedAStatus MockBroadcastRadioCallback::onCurrentProgramInfoChanged(const ProgramInfo& info) {
    LOG(DEBUG) << "onCurrentProgramInfoChanged with " << info.toString().c_str();
    {
        std::lock_guard<std::mutex> lk(mLock);
        mCurrentProgramInfo = info;
    }

    mOnCurrentProgramInfoChangedFlag.notify();
    return ndk::ScopedAStatus::ok();
}

ScopedAStatus MockBroadcastRadioCallback::onProgramListUpdated(
        [[maybe_unused]] const ProgramListChunk& chunk) {
    return ndk::ScopedAStatus::ok();
}

ScopedAStatus MockBroadcastRadioCallback::onParametersUpdated(
        [[maybe_unused]] const vector<VendorKeyValue>& parameters) {
    return ndk::ScopedAStatus::ok();
}

ScopedAStatus MockBroadcastRadioCallback::onAntennaStateChange(bool connected) {
    if (!connected) {
        std::lock_guard<std::mutex> lk(mLock);
        mAntennaConnectionState = false;
    }
    return ndk::ScopedAStatus::ok();
}

ScopedAStatus MockBroadcastRadioCallback::onConfigFlagUpdated([[maybe_unused]] ConfigFlag in_flag,
                                                              [[maybe_unused]] bool in_value) {
    return ndk::ScopedAStatus::ok();
}

bool MockBroadcastRadioCallback::waitOnCurrentProgramInfoChangedCallback() {
    return mOnCurrentProgramInfoChangedFlag.wait();
}

void MockBroadcastRadioCallback::reset() {
    mOnCurrentProgramInfoChangedFlag.reset();
}

bool MockBroadcastRadioCallback::isTunerFailed() {
    std::lock_guard<std::mutex> lk(mLock);
    return tunerFailed;
}

ProgramInfo MockBroadcastRadioCallback::getCurrentProgramInfo() {
    std::lock_guard<std::mutex> lk(mLock);
    return mCurrentProgramInfo;
}

}  // namespace aidl::android::hardware::broadcastradio
+103 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.
 */

#pragma once

#include <aidl/android/hardware/broadcastradio/BnTunerCallback.h>
#include <aidl/android/hardware/broadcastradio/ConfigFlag.h>
#include <aidl/android/hardware/broadcastradio/IBroadcastRadio.h>
#include <aidl/android/hardware/broadcastradio/ProgramInfo.h>
#include <aidl/android/hardware/broadcastradio/ProgramListChunk.h>
#include <aidl/android/hardware/broadcastradio/ProgramSelector.h>
#include <aidl/android/hardware/broadcastradio/Result.h>
#include <aidl/android/hardware/broadcastradio/VendorKeyValue.h>

#include <android-base/thread_annotations.h>

#include <broadcastradio-utils-aidl/Utils.h>

#include <condition_variable>

namespace aidl::android::hardware::broadcastradio {

namespace {
using ::ndk::ScopedAStatus;

}  // namespace

class MockBroadcastRadioCallback final : public BnTunerCallback {
  public:
    explicit MockBroadcastRadioCallback();
    ScopedAStatus onTuneFailed(Result result, const ProgramSelector& selector) override;
    ScopedAStatus onCurrentProgramInfoChanged(const ProgramInfo& info) override;
    ScopedAStatus onProgramListUpdated(const ProgramListChunk& chunk) override;
    ScopedAStatus onParametersUpdated(const std::vector<VendorKeyValue>& parameters) override;
    ScopedAStatus onAntennaStateChange(bool connected) override;
    ScopedAStatus onConfigFlagUpdated(ConfigFlag in_flag, bool in_value) override;

    bool waitOnCurrentProgramInfoChangedCallback();
    bool isTunerFailed();
    void reset();

    ProgramInfo getCurrentProgramInfo();

  private:
    class CallbackFlag final {
      public:
        CallbackFlag(int timeoutMs) { mTimeoutMs = timeoutMs; }
        /**
         * Notify that the callback is called.
         */
        void notify() {
            std::unique_lock<std::mutex> lock(mMutex);
            mCalled = true;
            lock.unlock();
            mCv.notify_all();
        };

        /**
         * Wait for the timeout passed into the constructor.
         */
        bool wait() {
            std::unique_lock<std::mutex> lock(mMutex);
            return mCv.wait_for(lock, std::chrono::milliseconds(mTimeoutMs),
                                [this] { return mCalled; });
        };

        /**
         * Reset the callback to not called.
         */
        void reset() {
            std::unique_lock<std::mutex> lock(mMutex);
            mCalled = false;
        }

      private:
        std::mutex mMutex;
        bool mCalled GUARDED_BY(mMutex) = false;
        std::condition_variable mCv;
        int mTimeoutMs;
    };

    std::mutex mLock;
    bool mAntennaConnectionState GUARDED_BY(mLock);
    bool tunerFailed GUARDED_BY(mLock) = false;
    ProgramInfo mCurrentProgramInfo GUARDED_BY(mLock);
    utils::ProgramInfoSet mProgramList GUARDED_BY(mLock);
    CallbackFlag mOnCurrentProgramInfoChangedFlag = CallbackFlag(IBroadcastRadio::TUNER_TIMEOUT_MS);
};

}  // namespace aidl::android::hardware::broadcastradio