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

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

Merge "Implement ProgramSelector at HIDL layer."

parents 69a4b8fe a02b6ef2
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -20,6 +20,27 @@ import @1.0::ITuner;

interface ITuner extends @1.0::ITuner {

    /**
     * Tune to a specified program.
     *
     * For AM/FM, it must be called when a valid configuration has been applied.
     * Automatically cancels pending scan, step or tune.
     *
     * If method returns OK, ITunerCallback.tuneComplete_1_1() MUST be called:
     * - once successfully tuned;
     * - after a time out;
     * - after a full band scan, if no station found.
     *
     * The tuned field of ProgramInfo should indicate if tuned to a valid
     * station or not.
     *
     * @param program Program to tune to.
     * @return result OK if successfully started tunning.
     *                INVALID_ARGUMENTS if invalid arguments are passed.
     *                NOT_INITIALIZED if another error occurs.
     */
    tune_1_1(ProgramSelector program) generates (Result result);

    /**
     * Retrieve current station information.
     * @return result OK if scan successfully started
+56 −28
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "BroadcastRadio.h"
#include "Tuner.h"

#include <Utils.h>
#include <log/log.h>

namespace android {
@@ -70,6 +71,8 @@ Return<Result> Tuner::setConfiguration(const BandConfig& config) {

        mAmfmConfig = move(config);
        mAmfmConfig.antennaConnected = true;
        mCurrentProgram = utils::make_selector(mAmfmConfig.type, mAmfmConfig.lowerLimit);

        mIsAmfmConfigSet = true;
        mCallback->configChange(Result::OK, mAmfmConfig);
    };
@@ -90,28 +93,31 @@ Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb) {
    return Void();
}

// makes ProgramInfo that points to no channel
static ProgramInfo makeDummyProgramInfo(uint32_t channel) {
// makes ProgramInfo that points to no program
static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
    ProgramInfo info11 = {};
    auto& info10 = info11.base;

    info10.channel = channel;
    utils::getLegacyChannel(selector, info10.channel, info10.subChannel);
    info11.selector = selector;
    info11.flags |= ProgramInfoFlags::MUTED;

    return info11;
}

void Tuner::tuneInternalLocked() {
void Tuner::tuneInternalLocked(const ProgramSelector& sel) {
    VirtualRadio* virtualRadio = nullptr;
    if (mAmfmConfig.type == Band::FM_HD || mAmfmConfig.type == Band::FM) {
        virtualRadio = &mVirtualFm;
    }

    VirtualProgram virtualProgram;
    if (virtualRadio != nullptr && virtualRadio->getProgram(mCurrentProgram, virtualProgram)) {
    if (virtualRadio != nullptr && virtualRadio->getProgram(sel, virtualProgram)) {
        mCurrentProgram = virtualProgram.selector;
        mCurrentProgramInfo = static_cast<ProgramInfo>(virtualProgram);
    } else {
        mCurrentProgramInfo = makeDummyProgramInfo(mCurrentProgram);
        mCurrentProgram = sel;
        mCurrentProgramInfo = makeDummyProgramInfo(sel);
    }
    mIsTuneCompleted = true;

@@ -152,7 +158,7 @@ Return<Result> Tuner::scan(Direction direction, bool skipSubChannel __unused) {
    auto found = lower_bound(list.begin(), list.end(), VirtualProgram({current}));
    if (direction == Direction::UP) {
        if (found < list.end() - 1) {
            if (found->channel == current) found++;
            if (utils::tunesTo(current, found->selector)) found++;
        } else {
            found = list.begin();
        }
@@ -163,25 +169,31 @@ Return<Result> Tuner::scan(Direction direction, bool skipSubChannel __unused) {
            found = list.end() - 1;
        }
    }
    auto tuneTo = found->channel;
    auto tuneTo = found->selector;

    mIsTuneCompleted = false;
    auto task = [this, tuneTo, direction]() {
        ALOGI("Performing scan %s", toString(direction).c_str());

        lock_guard<mutex> lk(mMut);
        mCurrentProgram = tuneTo;
        tuneInternalLocked();
        tuneInternalLocked(tuneTo);
    };
    mThread.schedule(task, gDefaultDelay.scan);

    return Result::OK;
}

Return<Result> Tuner::step(Direction direction, bool skipSubChannel __unused) {
Return<Result> Tuner::step(Direction direction, bool skipSubChannel) {
    ALOGV("%s", __func__);
    ALOGW_IF(!skipSubChannel, "can't step to next frequency without ignoring subChannel");

    lock_guard<mutex> lk(mMut);

    if (!utils::isAmFm(utils::getType(mCurrentProgram))) {
        ALOGE("Can't step in anything else than AM/FM");
        return Result::NOT_INITIALIZED;
    }

    ALOGW_IF(!mIsAmfmConfigSet, "AM/FM config not set");
    if (!mIsAmfmConfigSet) return Result::INVALID_STATE;
    mIsTuneCompleted = false;
@@ -191,16 +203,18 @@ Return<Result> Tuner::step(Direction direction, bool skipSubChannel __unused) {

        lock_guard<mutex> lk(mMut);

        auto current = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY, 0);

        if (direction == Direction::UP) {
            mCurrentProgram += mAmfmConfig.spacings[0];
            current += mAmfmConfig.spacings[0];
        } else {
            mCurrentProgram -= mAmfmConfig.spacings[0];
            current -= mAmfmConfig.spacings[0];
        }

        if (mCurrentProgram > mAmfmConfig.upperLimit) mCurrentProgram = mAmfmConfig.lowerLimit;
        if (mCurrentProgram < mAmfmConfig.lowerLimit) mCurrentProgram = mAmfmConfig.upperLimit;
        if (current > mAmfmConfig.upperLimit) current = mAmfmConfig.lowerLimit;
        if (current < mAmfmConfig.lowerLimit) current = mAmfmConfig.upperLimit;

        tuneInternalLocked();
        tuneInternalLocked(utils::make_selector(mAmfmConfig.type, current));
    };
    mThread.schedule(task, gDefaultDelay.step);

@@ -209,19 +223,33 @@ Return<Result> Tuner::step(Direction direction, bool skipSubChannel __unused) {

Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel) {
    ALOGV("%s(%d, %d)", __func__, channel, subChannel);
    Band band;
    {
        lock_guard<mutex> lk(mMut);
        band = mAmfmConfig.type;
    }
    return tune_1_1(utils::make_selector(band, channel, subChannel));
}

Return<Result> Tuner::tune_1_1(const ProgramSelector& sel) {
    ALOGV("%s(%s)", __func__, toString(sel).c_str());

    lock_guard<mutex> lk(mMut);

    if (utils::isAmFm(utils::getType(mCurrentProgram))) {
        ALOGW_IF(!mIsAmfmConfigSet, "AM/FM config not set");
        if (!mIsAmfmConfigSet) return Result::INVALID_STATE;
    if (channel < mAmfmConfig.lowerLimit || channel > mAmfmConfig.upperLimit) {

        auto freq = utils::getId(sel, IdentifierType::AMFM_FREQUENCY);
        if (freq < mAmfmConfig.lowerLimit || freq > mAmfmConfig.upperLimit) {
            return Result::INVALID_ARGUMENTS;
        }
    mIsTuneCompleted = false;
    }

    auto task = [this, channel]() {
    mIsTuneCompleted = false;
    auto task = [this, sel]() {
        lock_guard<mutex> lk(mMut);
        mCurrentProgram = channel;
        tuneInternalLocked();
        tuneInternalLocked(sel);
    };
    mThread.schedule(task, gDefaultDelay.tune);

+3 −2
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ struct Tuner : public ITuner {
    Return<Result> scan(V1_0::Direction direction, bool skipSubChannel) override;
    Return<Result> step(V1_0::Direction direction, bool skipSubChannel) override;
    Return<Result> tune(uint32_t channel, uint32_t subChannel) override;
    Return<Result> tune_1_1(const ProgramSelector& program) override;
    Return<Result> cancel() override;
    Return<void> getProgramInformation(getProgramInformation_cb _hidl_cb) override;
    Return<void> getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) override;
@@ -60,10 +61,10 @@ struct Tuner : public ITuner {
    bool mIsAmfmConfigSet = false;
    V1_0::BandConfig mAmfmConfig;
    bool mIsTuneCompleted = false;
    uint32_t mCurrentProgram;  // TODO(b/32621193): Station Selector
    ProgramSelector mCurrentProgram = {};
    ProgramInfo mCurrentProgramInfo = {};

    void tuneInternalLocked();
    void tuneInternalLocked(const ProgramSelector& sel);
};

}  // namespace implementation
+24 −3
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
 */
#include "VirtualProgram.h"

#include <Utils.h>

namespace android {
namespace hardware {
namespace broadcastradio {
@@ -29,10 +31,12 @@ VirtualProgram::operator ProgramInfo() const {
    ProgramInfo info11 = {};
    auto& info10 = info11.base;

    info10.channel = channel;
    utils::getLegacyChannel(selector, info10.channel, info10.subChannel);
    info11.selector = selector;
    info10.tuned = true;
    info10.stereo = true;
    info10.signalStrength = 100;
    info10.digital = utils::isDigital(selector);
    info10.signalStrength = info10.digital ? 100 : 80;

    info10.metadata = hidl_vec<MetaData>({
        {MetadataType::TEXT, MetadataKey::RDS_PS, {}, {}, programName, {}},
@@ -43,8 +47,25 @@ VirtualProgram::operator ProgramInfo() const {
    return info11;
}

// Defining order on virtual programs, how they appear on band.
// It's mostly for default implementation purposes, may not be complete or correct.
bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs) {
    return lhs.channel < rhs.channel;
    auto& l = lhs.selector;
    auto& r = rhs.selector;

    // Two programs with the same primaryId is considered the same.
    if (l.programType != r.programType) return l.programType < r.programType;
    if (l.primaryId.type != r.primaryId.type) return l.primaryId.type < r.primaryId.type;
    if (l.primaryId.value != r.primaryId.value) return l.primaryId.value < r.primaryId.value;

    // A little exception for HD Radio subchannel - we check secondary ID too.
    if (utils::hasId(l, IdentifierType::HD_SUBCHANNEL) &&
        utils::hasId(r, IdentifierType::HD_SUBCHANNEL)) {
        return utils::getId(l, IdentifierType::HD_SUBCHANNEL) <
               utils::getId(r, IdentifierType::HD_SUBCHANNEL);
    }

    return false;
}

}  // namespace implementation
+1 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ namespace V1_1 {
namespace implementation {

struct VirtualProgram {
    uint32_t channel;  // TODO(b/32621193): Station Selector
    ProgramSelector selector;

    std::string programName = "";
    std::string songArtist = "";
Loading