Loading broadcastradio/1.1/ITuner.hal +21 −0 Original line number Diff line number Diff line Loading @@ -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 Loading broadcastradio/1.1/default/Tuner.cpp +56 −28 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "BroadcastRadio.h" #include "Tuner.h" #include <Utils.h> #include <log/log.h> namespace android { Loading Loading @@ -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); }; Loading @@ -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; Loading Loading @@ -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(); } Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading broadcastradio/1.1/default/Tuner.h +3 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading broadcastradio/1.1/default/VirtualProgram.cpp +24 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ */ #include "VirtualProgram.h" #include <Utils.h> namespace android { namespace hardware { namespace broadcastradio { Loading @@ -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, {}}, Loading @@ -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 Loading broadcastradio/1.1/default/VirtualProgram.h +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
broadcastradio/1.1/ITuner.hal +21 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
broadcastradio/1.1/default/Tuner.cpp +56 −28 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "BroadcastRadio.h" #include "Tuner.h" #include <Utils.h> #include <log/log.h> namespace android { Loading Loading @@ -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); }; Loading @@ -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; Loading Loading @@ -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(); } Loading @@ -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; Loading @@ -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); Loading @@ -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); Loading
broadcastradio/1.1/default/Tuner.h +3 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading
broadcastradio/1.1/default/VirtualProgram.cpp +24 −3 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ */ #include "VirtualProgram.h" #include <Utils.h> namespace android { namespace hardware { namespace broadcastradio { Loading @@ -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, {}}, Loading @@ -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 Loading
broadcastradio/1.1/default/VirtualProgram.h +1 −1 Original line number Diff line number Diff line Loading @@ -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