From 90e39f542d2a3e70bf2faa3058abe3757973dc77 Mon Sep 17 00:00:00 2001 From: Weilin Xu Date: Tue, 7 Nov 2023 20:07:23 -0800 Subject: [PATCH] Improve DAB radio support in refrence bcRadio HAL Improved DAB radio support in the reference implementation for AIDL broadcast radio HAL. Used real DAB service ID, ECC code, freuqnecy and ensemble values for virtual DAB stations and implemented sub-channel support for DAB radio. Bug: 309693129 Test: atest VtsHalBroadcastradioAidlTargetTest Change-Id: I6a78794e16400f05c6d7c5ec99aa4978adca5b58 --- .../aidl/default/BroadcastRadio.cpp | 71 +++++++++++-------- .../aidl/default/VirtualProgram.cpp | 17 ++++- broadcastradio/aidl/default/VirtualRadio.cpp | 36 ++++++++-- broadcastradio/aidl/default/VirtualRadio.h | 1 + .../include/broadcastradio-utils-aidl/Utils.h | 6 ++ broadcastradio/common/utilsaidl/src/Utils.cpp | 15 ++++ 6 files changed, 110 insertions(+), 36 deletions(-) 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