mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:23:37 +00:00
Merge "Implement regional configuration fetching."
This commit is contained in:
committed by
Android (Google) Code Review
commit
0914a946b2
@@ -16,8 +16,12 @@ hidl_interface {
|
||||
"android.hidl.base@1.0",
|
||||
],
|
||||
types: [
|
||||
"AmFmBandRange",
|
||||
"AmFmRegionConfig",
|
||||
"ConfigFlag",
|
||||
"Constants",
|
||||
"DabTableEntry",
|
||||
"Deemphasis",
|
||||
"IdentifierType",
|
||||
"Metadata",
|
||||
"MetadataKey",
|
||||
@@ -28,6 +32,7 @@ hidl_interface {
|
||||
"ProgramListChunk",
|
||||
"ProgramSelector",
|
||||
"Properties",
|
||||
"Rds",
|
||||
"Result",
|
||||
"VendorKeyValue",
|
||||
],
|
||||
|
||||
@@ -32,6 +32,28 @@ interface IBroadcastRadio {
|
||||
*/
|
||||
getProperties() generates (Properties properties);
|
||||
|
||||
/**
|
||||
* Fetches current or possible AM/FM region configuration.
|
||||
*
|
||||
* @param full If true, returns full hardware capabilities.
|
||||
* If false, returns current regional configuration.
|
||||
* @return result OK in case of success.
|
||||
* NOT_SUPPORTED if the tuner doesn't support AM/FM.
|
||||
* @return config Hardware capabilities (full=true) or
|
||||
* current configuration (full=false).
|
||||
*/
|
||||
getAmFmRegionConfig(bool full)
|
||||
generates (Result result, AmFmRegionConfig config);
|
||||
|
||||
/**
|
||||
* Fetches current DAB region configuration.
|
||||
*
|
||||
* @return result OK in case of success.
|
||||
* NOT_SUPPORTED if the tuner doesn't support DAB.
|
||||
* @return config Current configuration.
|
||||
*/
|
||||
getDabRegionConfig() generates (Result result, vec<DabTableEntry> config);
|
||||
|
||||
/**
|
||||
* Opens a new tuner session.
|
||||
*
|
||||
|
||||
@@ -24,6 +24,9 @@ cc_binary {
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
],
|
||||
cppflags: [
|
||||
"-std=c++1z",
|
||||
],
|
||||
srcs: [
|
||||
"BroadcastRadio.cpp",
|
||||
"TunerSession.cpp",
|
||||
|
||||
@@ -33,6 +33,16 @@ using std::map;
|
||||
using std::mutex;
|
||||
using std::vector;
|
||||
|
||||
static const AmFmRegionConfig gDefaultAmFmConfig = { //
|
||||
{
|
||||
{87500, 108000, 100, 100}, // FM
|
||||
{153, 282, 3, 9}, // AM LW
|
||||
{531, 1620, 9, 9}, // AM MW
|
||||
{1600, 30000, 1, 5}, // AM SW
|
||||
},
|
||||
static_cast<uint32_t>(Deemphasis::D50),
|
||||
static_cast<uint32_t>(Rds::RDS)};
|
||||
|
||||
static Properties initProperties(const VirtualRadio& virtualRadio) {
|
||||
Properties prop = {};
|
||||
|
||||
@@ -51,7 +61,9 @@ static Properties initProperties(const VirtualRadio& virtualRadio) {
|
||||
}
|
||||
|
||||
BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio)
|
||||
: mVirtualRadio(virtualRadio), mProperties(initProperties(virtualRadio)) {}
|
||||
: mVirtualRadio(virtualRadio),
|
||||
mProperties(initProperties(virtualRadio)),
|
||||
mAmFmConfig(gDefaultAmFmConfig) {}
|
||||
|
||||
Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
|
||||
ALOGV("%s", __func__);
|
||||
@@ -59,6 +71,44 @@ Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
|
||||
return {};
|
||||
}
|
||||
|
||||
AmFmRegionConfig BroadcastRadio::getAmFmConfig() const {
|
||||
lock_guard<mutex> lk(mMut);
|
||||
return mAmFmConfig;
|
||||
}
|
||||
|
||||
Return<void> BroadcastRadio::getAmFmRegionConfig(bool full, getAmFmRegionConfig_cb _hidl_cb) {
|
||||
ALOGV("%s(%d)", __func__, full);
|
||||
|
||||
if (full) {
|
||||
AmFmRegionConfig config = {};
|
||||
config.ranges = hidl_vec<AmFmBandRange>({
|
||||
{65000, 108000, 10, 0}, // FM
|
||||
{150, 30000, 1, 0}, // AM
|
||||
});
|
||||
config.fmDeemphasis = Deemphasis::D50 | Deemphasis::D75;
|
||||
config.fmRds = Rds::RDS | Rds::RBDS;
|
||||
_hidl_cb(Result::OK, config);
|
||||
return {};
|
||||
} else {
|
||||
_hidl_cb(Result::OK, getAmFmConfig());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Return<void> BroadcastRadio::getDabRegionConfig(getDabRegionConfig_cb _hidl_cb) {
|
||||
ALOGV("%s", __func__);
|
||||
|
||||
hidl_vec<DabTableEntry> config = {
|
||||
{"5A", 174928}, {"7D", 194064}, {"8A", 195936}, {"8B", 197648}, {"9A", 202928},
|
||||
{"9B", 204640}, {"9C", 206352}, {"10B", 211648}, {"10C", 213360}, {"10D", 215072},
|
||||
{"11A", 216928}, {"11B", 218640}, {"11C", 220352}, {"11D", 222064}, {"12A", 223936},
|
||||
{"12B", 225648}, {"12C", 227360}, {"12D", 229072},
|
||||
};
|
||||
|
||||
_hidl_cb(Result::OK, config);
|
||||
return {};
|
||||
}
|
||||
|
||||
Return<void> BroadcastRadio::openSession(const sp<ITunerCallback>& callback,
|
||||
openSession_cb _hidl_cb) {
|
||||
ALOGV("%s", __func__);
|
||||
|
||||
@@ -32,14 +32,19 @@ struct BroadcastRadio : public IBroadcastRadio {
|
||||
|
||||
// V2_0::IBroadcastRadio methods
|
||||
Return<void> getProperties(getProperties_cb _hidl_cb) override;
|
||||
Return<void> getAmFmRegionConfig(bool full, getAmFmRegionConfig_cb _hidl_cb);
|
||||
Return<void> getDabRegionConfig(getDabRegionConfig_cb _hidl_cb);
|
||||
Return<void> openSession(const sp<ITunerCallback>& callback, openSession_cb _hidl_cb) override;
|
||||
Return<void> getImage(uint32_t id, getImage_cb _hidl_cb);
|
||||
|
||||
std::reference_wrapper<const VirtualRadio> mVirtualRadio;
|
||||
Properties mProperties;
|
||||
|
||||
AmFmRegionConfig getAmFmConfig() const;
|
||||
|
||||
private:
|
||||
std::mutex mMut;
|
||||
mutable std::mutex mMut;
|
||||
AmFmRegionConfig mAmFmConfig;
|
||||
wp<TunerSession> mSession;
|
||||
};
|
||||
|
||||
|
||||
@@ -77,8 +77,12 @@ void TunerSession::tuneInternalLocked(const ProgramSelector& sel) {
|
||||
mCallback->onCurrentProgramInfoChanged(programInfo);
|
||||
}
|
||||
|
||||
const BroadcastRadio& TunerSession::module() const {
|
||||
return mModule.get();
|
||||
}
|
||||
|
||||
const VirtualRadio& TunerSession::virtualRadio() const {
|
||||
return mModule.get().mVirtualRadio;
|
||||
return module().mVirtualRadio;
|
||||
}
|
||||
|
||||
Return<Result> TunerSession::tune(const ProgramSelector& sel) {
|
||||
@@ -86,7 +90,7 @@ Return<Result> TunerSession::tune(const ProgramSelector& sel) {
|
||||
lock_guard<mutex> lk(mMut);
|
||||
if (mIsClosed) return Result::INVALID_STATE;
|
||||
|
||||
if (!utils::isSupported(mModule.get().mProperties, sel)) {
|
||||
if (!utils::isSupported(module().mProperties, sel)) {
|
||||
ALOGW("Selector not supported");
|
||||
return Result::NOT_SUPPORTED;
|
||||
}
|
||||
@@ -170,23 +174,19 @@ Return<Result> TunerSession::step(bool directionUp) {
|
||||
mIsTuneCompleted = false;
|
||||
|
||||
auto stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
|
||||
#if 0
|
||||
// TODO(b/69958423): handle regions
|
||||
if (directionUp) {
|
||||
stepTo += mAmfmConfig.spacings[0];
|
||||
} else {
|
||||
stepTo -= mAmfmConfig.spacings[0];
|
||||
auto range = getAmFmRangeLocked();
|
||||
if (!range) {
|
||||
ALOGE("Can't find current band");
|
||||
return Result::INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (stepTo > mAmfmConfig.upperLimit) stepTo = mAmfmConfig.lowerLimit;
|
||||
if (stepTo < mAmfmConfig.lowerLimit) stepTo = mAmfmConfig.upperLimit;
|
||||
#else
|
||||
if (directionUp) {
|
||||
stepTo += 100;
|
||||
stepTo += range->spacing;
|
||||
} else {
|
||||
stepTo -= 100;
|
||||
stepTo -= range->spacing;
|
||||
}
|
||||
#endif
|
||||
if (stepTo > range->upperBound) stepTo = range->lowerBound;
|
||||
if (stepTo < range->lowerBound) stepTo = range->upperBound;
|
||||
|
||||
auto task = [this, stepTo]() {
|
||||
ALOGI("Performing step to %s", std::to_string(stepTo).c_str());
|
||||
@@ -280,6 +280,18 @@ Return<void> TunerSession::close() {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<AmFmBandRange> TunerSession::getAmFmRangeLocked() const {
|
||||
if (!mIsTuneCompleted) return {};
|
||||
if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) return {};
|
||||
|
||||
auto freq = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
|
||||
for (auto&& range : module().getAmFmConfig().ranges) {
|
||||
if (range.lowerBound <= freq && range.upperBound >= freq) return range;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_0
|
||||
} // namespace broadcastradio
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <android/hardware/broadcastradio/2.0/ITunerSession.h>
|
||||
#include <broadcastradio-utils/WorkerThread.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace broadcastradio {
|
||||
@@ -48,6 +50,8 @@ struct TunerSession : public ITunerSession {
|
||||
getParameters_cb _hidl_cb) override;
|
||||
virtual Return<void> close() override;
|
||||
|
||||
std::optional<AmFmBandRange> getAmFmRangeLocked() const;
|
||||
|
||||
private:
|
||||
std::mutex mMut;
|
||||
WorkerThread mThread;
|
||||
@@ -61,6 +65,7 @@ struct TunerSession : public ITunerSession {
|
||||
|
||||
void tuneInternalLocked(const ProgramSelector& sel);
|
||||
const VirtualRadio& virtualRadio() const;
|
||||
const BroadcastRadio& module() const;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
@@ -32,6 +32,7 @@ enum Constants : int32_t {
|
||||
enum Result : int32_t {
|
||||
OK,
|
||||
UNKNOWN_ERROR,
|
||||
INTERNAL_ERROR,
|
||||
INVALID_ARGUMENTS,
|
||||
INVALID_STATE,
|
||||
NOT_SUPPORTED,
|
||||
@@ -119,6 +120,108 @@ struct VendorKeyValue {
|
||||
string value;
|
||||
};
|
||||
|
||||
/**
|
||||
* A supported or configured RDS variant.
|
||||
*
|
||||
* Both might be set for hardware capabilities check (with full=true when
|
||||
* calling getAmFmRegionConfig), but only one (or none) for specific
|
||||
* region settings.
|
||||
*/
|
||||
enum Rds : uint8_t {
|
||||
/** Standard variant, used everywhere except North America. */
|
||||
RDS = 1 << 0,
|
||||
|
||||
/** Variant used in North America. */
|
||||
RBDS = 1 << 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* FM de-emphasis filter supported or configured.
|
||||
*
|
||||
* Both might be set for hardware capabilities check (with full=true when
|
||||
* calling getAmFmRegionConfig), but exactly one for specific region settings.
|
||||
*/
|
||||
enum Deemphasis : uint8_t {
|
||||
D50 = 1 << 0,
|
||||
D75 = 1 << 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Regional configuration for AM/FM.
|
||||
*
|
||||
* For hardware capabilities check (with full=true when calling
|
||||
* getAmFmRegionConfig), HAL implementation fills entire supported range of
|
||||
* frequencies and features.
|
||||
*
|
||||
* When checking current configuration, at most one bit in each bitfield
|
||||
* can be set.
|
||||
*/
|
||||
struct AmFmRegionConfig {
|
||||
/**
|
||||
* All supported or configured AM/FM bands.
|
||||
*
|
||||
* AM/FM bands are identified by frequency value
|
||||
* (see IdentifierType::AMFM_FREQUENCY).
|
||||
*
|
||||
* With typical configuration, it's expected to have two frequency ranges
|
||||
* for capabilities check (AM and FM) and four ranges for specific region
|
||||
* configuration (AM LW, AM MW, AM SW, FM).
|
||||
*/
|
||||
vec<AmFmBandRange> ranges;
|
||||
|
||||
/** De-emphasis filter supported/configured. */
|
||||
bitfield<Deemphasis> fmDeemphasis;
|
||||
|
||||
/** RDS/RBDS variant supported/configured. */
|
||||
bitfield<Rds> fmRds;
|
||||
};
|
||||
|
||||
/**
|
||||
* AM/FM band range for region configuration.
|
||||
*
|
||||
* Defines channel grid: each possible channel is set at
|
||||
* lowerBound + channelNumber * spacing, up to upperBound.
|
||||
*/
|
||||
struct AmFmBandRange {
|
||||
/** The frequency of the first channel within the range. */
|
||||
uint32_t lowerBound;
|
||||
|
||||
/** The frequency of the last channel within the range. */
|
||||
uint32_t upperBound;
|
||||
|
||||
/** Channel grid resolution, how far apart are the channels. */
|
||||
uint32_t spacing;
|
||||
|
||||
/**
|
||||
* Spacing used when scanning for channels. It's a multiply of spacing and
|
||||
* allows to skip some channels when scanning to make it faster.
|
||||
*
|
||||
* Tuner may first quickly check every n-th channel and if it detects echo
|
||||
* from a station, it fine-tunes to find the exact frequency.
|
||||
*
|
||||
* It's ignored for capabilities check (with full=true when calling
|
||||
* getAmFmRegionConfig).
|
||||
*/
|
||||
uint32_t scanSpacing;
|
||||
};
|
||||
|
||||
/**
|
||||
* An entry in regional configuration for DAB.
|
||||
*
|
||||
* Defines a frequency table row for ensembles.
|
||||
*/
|
||||
struct DabTableEntry {
|
||||
/**
|
||||
* Channel name, i.e. 5A, 7B.
|
||||
*
|
||||
* It must match the following regular expression: /^[A-Z0-9]{2,5}$/.
|
||||
*/
|
||||
string label;
|
||||
|
||||
/** Frequency, in kHz. */
|
||||
uint32_t frequency;
|
||||
};
|
||||
|
||||
/**
|
||||
* Properties of a given broadcast radio module.
|
||||
*/
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
#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 <chrono>
|
||||
#include <regex>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -93,6 +95,7 @@ class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase {
|
||||
virtual void TearDown() override;
|
||||
|
||||
bool openSession();
|
||||
bool getAmFmRegionConfig(bool full, AmFmRegionConfig* config);
|
||||
|
||||
sp<IBroadcastRadio> mModule;
|
||||
Properties mProperties;
|
||||
@@ -159,6 +162,22 @@ bool BroadcastRadioHalTest::openSession() {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test session opening.
|
||||
*
|
||||
@@ -181,6 +200,127 @@ TEST_F(BroadcastRadioHalTest, OpenSession) {
|
||||
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;
|
||||
* - scan spacing is a multiply of manual spacing value.
|
||||
*/
|
||||
TEST_F(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;
|
||||
* - scan spacing is not set.
|
||||
*/
|
||||
TEST_F(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_F(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]{2,5}$");
|
||||
// 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("123ABC", 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.
|
||||
*
|
||||
|
||||
@@ -89,6 +89,18 @@ IdentifierIterator end(const V2_0::ProgramSelector& sel) {
|
||||
return IdentifierIterator(sel) + 1 /* primary id */ + sel.secondaryIds.size();
|
||||
}
|
||||
|
||||
FrequencyBand getBand(uint64_t freq) {
|
||||
// keep in sync with
|
||||
// frameworks/base/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
|
||||
if (freq < 30) return FrequencyBand::UNKNOWN;
|
||||
if (freq < 500) return FrequencyBand::AM_LW;
|
||||
if (freq < 1705) return FrequencyBand::AM_MW;
|
||||
if (freq < 30000) return FrequencyBand::AM_SW;
|
||||
if (freq < 60000) return FrequencyBand::UNKNOWN;
|
||||
if (freq < 110000) return FrequencyBand::FM;
|
||||
return FrequencyBand::UNKNOWN;
|
||||
}
|
||||
|
||||
static bool bothHaveId(const ProgramSelector& a, const ProgramSelector& b,
|
||||
const IdentifierType type) {
|
||||
return hasId(a, type) && hasId(b, type);
|
||||
@@ -194,7 +206,7 @@ bool isSupported(const Properties& prop, const ProgramSelector& sel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isValid(const ProgramIdentifier& id) {
|
||||
bool isValid(const ProgramIdentifier& id) {
|
||||
auto val = id.value;
|
||||
bool valid = true;
|
||||
|
||||
@@ -209,8 +221,10 @@ static bool isValid(const ProgramIdentifier& id) {
|
||||
case IdentifierType::INVALID:
|
||||
expect(false, "IdentifierType::INVALID");
|
||||
break;
|
||||
case IdentifierType::AMFM_FREQUENCY:
|
||||
case IdentifierType::DAB_FREQUENCY:
|
||||
expect(val > 100000u, "f > 100MHz");
|
||||
// fallthrough
|
||||
case IdentifierType::AMFM_FREQUENCY:
|
||||
case IdentifierType::DRMO_FREQUENCY:
|
||||
expect(val > 100u, "f > 100kHz");
|
||||
expect(val < 10000000u, "f < 10GHz");
|
||||
|
||||
@@ -27,6 +27,14 @@ namespace hardware {
|
||||
namespace broadcastradio {
|
||||
namespace utils {
|
||||
|
||||
enum class FrequencyBand {
|
||||
UNKNOWN,
|
||||
FM,
|
||||
AM_LW,
|
||||
AM_MW,
|
||||
AM_SW,
|
||||
};
|
||||
|
||||
V2_0::IdentifierType getType(uint32_t typeAsInt);
|
||||
V2_0::IdentifierType getType(const V2_0::ProgramIdentifier& id);
|
||||
|
||||
@@ -63,6 +71,16 @@ class IdentifierIterator
|
||||
IdentifierIterator begin(const V2_0::ProgramSelector& sel);
|
||||
IdentifierIterator end(const V2_0::ProgramSelector& sel);
|
||||
|
||||
/**
|
||||
* Guesses band from the frequency value.
|
||||
*
|
||||
* The band bounds are not exact to cover multiple regions.
|
||||
* The function is biased towards success, i.e. it never returns
|
||||
* FrequencyBand::UNKNOWN for correct frequency, but a result for
|
||||
* incorrect one is undefined (it doesn't have to return UNKNOWN).
|
||||
*/
|
||||
FrequencyBand getBand(uint64_t frequency);
|
||||
|
||||
/**
|
||||
* Checks, if {@code pointer} tunes to {@channel}.
|
||||
*
|
||||
@@ -105,6 +123,7 @@ std::vector<uint64_t> getAllIds(const V2_0::ProgramSelector& sel, const V2_0::Id
|
||||
*/
|
||||
bool isSupported(const V2_0::Properties& prop, const V2_0::ProgramSelector& sel);
|
||||
|
||||
bool isValid(const V2_0::ProgramIdentifier& id);
|
||||
bool isValid(const V2_0::ProgramSelector& sel);
|
||||
|
||||
V2_0::ProgramIdentifier make_identifier(V2_0::IdentifierType type, uint64_t value);
|
||||
|
||||
Reference in New Issue
Block a user