diff --git a/broadcastradio/aidl/default/BroadcastRadio.cpp b/broadcastradio/aidl/default/BroadcastRadio.cpp index 3af560f62c..4d6d81dc1d 100644 --- a/broadcastradio/aidl/default/BroadcastRadio.cpp +++ b/broadcastradio/aidl/default/BroadcastRadio.cpp @@ -66,12 +66,7 @@ Properties initProperties(const VirtualRadio& virtualRadio) { prop.maker = "Android"; prop.product = virtualRadio.getName(); - prop.supportedIdentifierTypes = vector({ - IdentifierType::AMFM_FREQUENCY_KHZ, - IdentifierType::RDS_PI, - IdentifierType::HD_STATION_ID_EXT, - IdentifierType::DAB_SID_EXT, - }); + prop.supportedIdentifierTypes = virtualRadio.getSupportedIdentifierTypes(); prop.vendorInfo = vector({ {"com.android.sample", "sample"}, }); @@ -352,7 +347,9 @@ bool BroadcastRadio::findNextLocked(const ProgramSelector& current, bool directi } // The list is not sorted here since it has already stored in VirtualRadio. bool hasAmFmFrequency = utils::hasAmFmFrequency(current); - uint32_t currentFreq = hasAmFmFrequency ? utils::getAmFmFrequency(current) : 0; + bool hasDabSId = utils::hasId(current, IdentifierType::DAB_SID_EXT); + uint32_t currentChannel = + hasAmFmFrequency ? utils::getAmFmFrequency(current) : utils::getDabSId(current); auto found = std::lower_bound(mProgramList.begin(), mProgramList.end(), VirtualProgram({current})); if (directionUp) { @@ -364,18 +361,22 @@ bool BroadcastRadio::findNextLocked(const ProgramSelector& current, bool directi // jump to the first selector which is greater than and of the same band as the current // program selector. if (utils::tunesTo(current, found->selector)) found++; - if (skipSubChannel && hasAmFmFrequency) { - auto firstFound = found; - while (utils::getAmFmFrequency(found->selector) == currentFreq) { - if (found < mProgramList.end() - 1) { - found++; - } else { - found = mProgramList.begin(); - } - if (found == firstFound) { - // Only one main channel exists in the program list, the tuner cannot skip - // sub-channel to the next program selector. - return false; + if (skipSubChannel) { + if (hasAmFmFrequency || hasDabSId) { + auto firstFound = found; + while ((hasAmFmFrequency && + utils::getAmFmFrequency(found->selector) == currentChannel) || + (hasDabSId && utils::getDabSId(found->selector) == currentChannel)) { + if (found < mProgramList.end() - 1) { + found++; + } else { + found = mProgramList.begin(); + } + if (found == firstFound) { + // Only one main channel exists in the program list, the tuner cannot + // skip sub-channel to the next program selector. + return false; + } } } } @@ -394,9 +395,11 @@ bool BroadcastRadio::findNextLocked(const ProgramSelector& current, bool directi // Otherwise, the tuner will jump to the first selector less than and of the same band // as the current program selector. found--; - if (hasAmFmFrequency && utils::hasAmFmFrequency(found->selector)) { - uint32_t nextFreq = utils::getAmFmFrequency(found->selector); - if (nextFreq != currentFreq) { + if ((hasAmFmFrequency && utils::hasAmFmFrequency(found->selector)) || + (hasDabSId && utils::hasId(found->selector, IdentifierType::DAB_SID_EXT))) { + uint32_t nextChannel = hasAmFmFrequency ? utils::getAmFmFrequency(found->selector) + : utils::getDabSId(found->selector); + if (nextChannel != currentChannel) { jumpToFirstSubChannelLocked(found); } else if (skipSubChannel) { jumpToFirstSubChannelLocked(found); @@ -429,16 +432,28 @@ bool BroadcastRadio::findNextLocked(const ProgramSelector& current, bool directi } void BroadcastRadio::jumpToFirstSubChannelLocked(vector::const_iterator& it) const { - if (!utils::hasAmFmFrequency(it->selector) || it == mProgramList.begin()) { + if (it == mProgramList.begin()) { return; } - uint32_t currentFrequency = utils::getAmFmFrequency(it->selector); - it--; - while (it != mProgramList.begin() && utils::hasAmFmFrequency(it->selector) && - utils::getAmFmFrequency(it->selector) == currentFrequency) { + bool hasAmFmFrequency = utils::hasAmFmFrequency(it->selector); + bool hasDabSId = utils::hasId(it->selector, IdentifierType::DAB_SID_EXT); + if (hasAmFmFrequency || hasDabSId) { + uint32_t currentChannel = hasAmFmFrequency ? utils::getAmFmFrequency(it->selector) + : utils::getDabSId(it->selector); it--; + while (it != mProgramList.begin()) { + if (hasAmFmFrequency && utils::hasAmFmFrequency(it->selector) && + utils::getAmFmFrequency(it->selector) == currentChannel) { + it--; + } else if (hasDabSId && utils::hasId(it->selector, IdentifierType::DAB_SID_EXT) && + utils::getDabSId(it->selector) == currentChannel) { + it--; + } else { + break; + } + } + it++; } - it++; } ScopedAStatus BroadcastRadio::seek(bool directionUp, bool skipSubChannel) { diff --git a/broadcastradio/aidl/default/VirtualProgram.cpp b/broadcastradio/aidl/default/VirtualProgram.cpp index 19c1dcfea6..dca431d68a 100644 --- a/broadcastradio/aidl/default/VirtualProgram.cpp +++ b/broadcastradio/aidl/default/VirtualProgram.cpp @@ -111,14 +111,25 @@ bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs) { return freq1 < freq2 || (freq1 == freq2 && (l.primaryId.type < r.primaryId.type || subChannel1 < subChannel2)); } else if (l.primaryId.type == IdentifierType::DAB_SID_EXT && - l.primaryId.type == IdentifierType::DAB_SID_EXT) { + r.primaryId.type == IdentifierType::DAB_SID_EXT) { uint64_t dabFreq1 = utils::getId(l, IdentifierType::DAB_FREQUENCY_KHZ); uint64_t dabFreq2 = utils::getId(r, IdentifierType::DAB_FREQUENCY_KHZ); if (dabFreq1 != dabFreq2) { return dabFreq1 < dabFreq2; } - return utils::getId(l, IdentifierType::DAB_ENSEMBLE) < - utils::getId(r, IdentifierType::DAB_ENSEMBLE); + uint32_t ecc1 = utils::getDabEccCode(l); + uint32_t ecc2 = utils::getDabEccCode(r); + if (ecc1 != ecc2) { + return ecc1 < ecc2; + } + uint64_t dabEnsemble1 = utils::getId(l, IdentifierType::DAB_ENSEMBLE); + uint64_t dabEnsemble2 = utils::getId(r, IdentifierType::DAB_ENSEMBLE); + if (dabEnsemble1 != dabEnsemble2) { + return dabEnsemble1 < dabEnsemble2; + } + uint32_t sId1 = utils::getDabSId(l); + uint32_t sId2 = utils::getDabSId(r); + return sId1 < sId2 || (sId1 == sId2 && utils::getDabSCIdS(l) < utils::getDabSCIdS(r)); } if (l.primaryId.type != r.primaryId.type) { diff --git a/broadcastradio/aidl/default/VirtualRadio.cpp b/broadcastradio/aidl/default/VirtualRadio.cpp index ba43d8a2f1..d6e58cd649 100644 --- a/broadcastradio/aidl/default/VirtualRadio.cpp +++ b/broadcastradio/aidl/default/VirtualRadio.cpp @@ -16,6 +16,7 @@ #include "VirtualRadio.h" #include +#include namespace aidl::android::hardware::broadcastradio { @@ -23,6 +24,7 @@ using ::aidl::android::hardware::broadcastradio::utils::makeSelectorAmfm; using ::aidl::android::hardware::broadcastradio::utils::makeSelectorDab; using ::aidl::android::hardware::broadcastradio::utils::makeSelectorHd; using ::std::string; +using ::std::unordered_set; using ::std::vector; VirtualRadio::VirtualRadio(const string& name, const vector& initialList) @@ -62,6 +64,20 @@ bool VirtualRadio::getProgram(const ProgramSelector& selector, VirtualProgram* p return false; } +vector VirtualRadio::getSupportedIdentifierTypes() const { + unordered_set supportedIdentifierTypeSet; + for (const auto& program : mPrograms) { + IdentifierType type = program.selector.primaryId.type; + if (supportedIdentifierTypeSet.count(type)) { + continue; + } + supportedIdentifierTypeSet.insert(type); + } + vector supportedIdentifierTypes(supportedIdentifierTypeSet.begin(), + supportedIdentifierTypeSet.end()); + return supportedIdentifierTypes; +} + // get singleton of AMFM Virtual Radio const VirtualRadio& VirtualRadio::getAmFmRadio() { // clang-format off @@ -103,14 +119,24 @@ const VirtualRadio& VirtualRadio::getDabRadio() { static VirtualRadio dabRadioMock( "DAB radio mock", { - {makeSelectorDab(/* sidExt= */ 0xA000000001u, /* ensemble= */ 0x0001u, + {makeSelectorDab(/* sidExt= */ 0x0E10000C221u, /* ensemble= */ 0xCE15u, /* freq= */ 225648u), "BBC Radio 1", "Khalid", "Talk"}, - {makeSelectorDab(/* sidExt= */ 0xB000000001u, /* ensemble= */ 0x1001u, + {makeSelectorDab(/* sidExt= */ 0x0E10000C222u, /* ensemble= */ 0xCE15u, + /* freq= */ 225648u), "BBC Radio 2", "Khalid", "Talk"}, + {makeSelectorDab(/* sidExt= */ 0xE10000C224u, /* ensemble= */ 0xCE15u, + /* freq= */ 225648u), "BBC Radio 4", "ArtistBBC1", "TitleCountry1"}, + {makeSelectorDab(/* sidExt= */ 0x1E10000C224u, /* ensemble= */ 0xCE15u, + /* freq= */ 225648u), "BBC Radio 4 LW", "ArtistBBC2", "TitleCountry2"}, + {makeSelectorDab(/* sidExt= */ 0x0E10000C21Au, /* ensemble= */ 0xC181u, /* freq= */ 222064u), "Classic FM", "Jean Sibelius", "Andante Festivo"}, - {makeSelectorDab(/* sidExt= */ 0xB000000002u, /* ensemble= */ 0x1002u, - /* freq= */ 227360u), "Absolute Radio", "Coldplay", "Clocks"}, - {makeSelectorDab(/* sidExt= */ 0xB000000002u, /* ensemble= */ 0x1002u, + {makeSelectorDab(/* sidExt= */ 0x0E10000C1C0u, /* ensemble= */ 0xC181u, + /* freq= */ 223936u), "Absolute Radio", "Coldplay", "Clocks"}, + {makeSelectorDab(/* sidExt= */ 0x0E10000C1C0u, /* ensemble= */ 0xC181u, /* freq= */ 222064u), "Absolute Radio", "Coldplay", "Clocks"}, + {makeSelectorDab(/* sidExt= */ 0x0E10000CCE7u, /* ensemble= */ 0xC19Du, + /* freq= */ 218640u), "Absolute Radio Country", "ArtistCountry1", "TitleCountry1"}, + {makeSelectorDab(/* sidExt= */ 0x0E10000CCE7u, /* ensemble= */ 0xC1A0u, + /* freq= */ 218640u), "Absolute Radio Country", "ArtistCountry2", "TitleCountry2"}, }); // clang-format on return dabRadioMock; diff --git a/broadcastradio/aidl/default/VirtualRadio.h b/broadcastradio/aidl/default/VirtualRadio.h index ae039c463c..0d70aefa57 100644 --- a/broadcastradio/aidl/default/VirtualRadio.h +++ b/broadcastradio/aidl/default/VirtualRadio.h @@ -36,6 +36,7 @@ class VirtualRadio final { std::string getName() const; const std::vector& getProgramList() const; bool getProgram(const ProgramSelector& selector, VirtualProgram* program) const; + std::vector getSupportedIdentifierTypes() const; static const VirtualRadio& getAmFmRadio(); static const VirtualRadio& getDabRadio(); diff --git a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h index a139e00896..bb43903707 100644 --- a/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h +++ b/broadcastradio/common/utilsaidl/include/broadcastradio-utils-aidl/Utils.h @@ -163,6 +163,12 @@ uint32_t getHdFrequency(const ProgramSelector& sel); int getHdSubchannel(const ProgramSelector& sel); +uint32_t getDabSId(const ProgramSelector& sel); + +int getDabEccCode(const ProgramSelector& sel); + +int getDabSCIdS(const ProgramSelector& sel); + bool hasAmFmFrequency(const ProgramSelector& sel); uint32_t getAmFmFrequency(const ProgramSelector& sel); diff --git a/broadcastradio/common/utilsaidl/src/Utils.cpp b/broadcastradio/common/utilsaidl/src/Utils.cpp index 4c99514886..76c3c6a36d 100644 --- a/broadcastradio/common/utilsaidl/src/Utils.cpp +++ b/broadcastradio/common/utilsaidl/src/Utils.cpp @@ -489,6 +489,21 @@ IdentifierType getType(int typeAsInt) { return static_cast(typeAsInt); } +uint32_t getDabSId(const ProgramSelector& sel) { + int64_t dabSidExt = getId(sel, IdentifierType::DAB_SID_EXT, /* defaultValue */ 0); + return static_cast(dabSidExt & 0xFFFFFFFF); +} + +int getDabEccCode(const ProgramSelector& sel) { + int64_t dabSidExt = getId(sel, IdentifierType::DAB_SID_EXT, /* defaultValue */ 0); + return static_cast((dabSidExt >> 32) & 0xFF); +} + +int getDabSCIdS(const ProgramSelector& sel) { + int64_t dabSidExt = getId(sel, IdentifierType::DAB_SID_EXT, /* defaultValue */ 0); + return static_cast((dabSidExt >> 40) & 0xF); +} + int getHdSubchannel(const ProgramSelector& sel) { int64_t hdSidExt = getId(sel, IdentifierType::HD_STATION_ID_EXT, kValueForNotFoundIdentifier); hdSidExt >>= 32; // Station ID number