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
diff --git a/broadcastradio/aidl/default/BroadcastRadio.cpp b/broadcastradio/aidl/default/BroadcastRadio.cpp
index 3af560f..4d6d81d 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.cpp
+++ b/broadcastradio/aidl/default/BroadcastRadio.cpp
@@ -66,12 +66,7 @@
prop.maker = "Android";
prop.product = virtualRadio.getName();
- prop.supportedIdentifierTypes = vector<IdentifierType>({
- IdentifierType::AMFM_FREQUENCY_KHZ,
- IdentifierType::RDS_PI,
- IdentifierType::HD_STATION_ID_EXT,
- IdentifierType::DAB_SID_EXT,
- });
+ prop.supportedIdentifierTypes = virtualRadio.getSupportedIdentifierTypes();
prop.vendorInfo = vector<VendorKeyValue>({
{"com.android.sample", "sample"},
});
@@ -352,7 +347,9 @@
}
// 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 @@
// 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 @@
// 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 @@
}
void BroadcastRadio::jumpToFirstSubChannelLocked(vector<VirtualProgram>::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 19c1dcf..dca431d 100644
--- a/broadcastradio/aidl/default/VirtualProgram.cpp
+++ b/broadcastradio/aidl/default/VirtualProgram.cpp
@@ -111,14 +111,25 @@
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 ba43d8a..d6e58cd 100644
--- a/broadcastradio/aidl/default/VirtualRadio.cpp
+++ b/broadcastradio/aidl/default/VirtualRadio.cpp
@@ -16,6 +16,7 @@
#include "VirtualRadio.h"
#include <broadcastradio-utils-aidl/Utils.h>
+#include <unordered_set>
namespace aidl::android::hardware::broadcastradio {
@@ -23,6 +24,7 @@
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<VirtualProgram>& initialList)
@@ -62,6 +64,20 @@
return false;
}
+vector<IdentifierType> VirtualRadio::getSupportedIdentifierTypes() const {
+ unordered_set<IdentifierType> supportedIdentifierTypeSet;
+ for (const auto& program : mPrograms) {
+ IdentifierType type = program.selector.primaryId.type;
+ if (supportedIdentifierTypeSet.count(type)) {
+ continue;
+ }
+ supportedIdentifierTypeSet.insert(type);
+ }
+ vector<IdentifierType> supportedIdentifierTypes(supportedIdentifierTypeSet.begin(),
+ supportedIdentifierTypeSet.end());
+ return supportedIdentifierTypes;
+}
+
// get singleton of AMFM Virtual Radio
const VirtualRadio& VirtualRadio::getAmFmRadio() {
// clang-format off
@@ -103,14 +119,24 @@
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 ae039c4..0d70aef 100644
--- a/broadcastradio/aidl/default/VirtualRadio.h
+++ b/broadcastradio/aidl/default/VirtualRadio.h
@@ -36,6 +36,7 @@
std::string getName() const;
const std::vector<VirtualProgram>& getProgramList() const;
bool getProgram(const ProgramSelector& selector, VirtualProgram* program) const;
+ std::vector<IdentifierType> 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 a139e00..bb43903 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 @@
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 4c99514..76c3c6a 100644
--- a/broadcastradio/common/utilsaidl/src/Utils.cpp
+++ b/broadcastradio/common/utilsaidl/src/Utils.cpp
@@ -489,6 +489,21 @@
return static_cast<IdentifierType>(typeAsInt);
}
+uint32_t getDabSId(const ProgramSelector& sel) {
+ int64_t dabSidExt = getId(sel, IdentifierType::DAB_SID_EXT, /* defaultValue */ 0);
+ return static_cast<uint32_t>(dabSidExt & 0xFFFFFFFF);
+}
+
+int getDabEccCode(const ProgramSelector& sel) {
+ int64_t dabSidExt = getId(sel, IdentifierType::DAB_SID_EXT, /* defaultValue */ 0);
+ return static_cast<uint32_t>((dabSidExt >> 32) & 0xFF);
+}
+
+int getDabSCIdS(const ProgramSelector& sel) {
+ int64_t dabSidExt = getId(sel, IdentifierType::DAB_SID_EXT, /* defaultValue */ 0);
+ return static_cast<uint32_t>((dabSidExt >> 40) & 0xF);
+}
+
int getHdSubchannel(const ProgramSelector& sel) {
int64_t hdSidExt = getId(sel, IdentifierType::HD_STATION_ID_EXT, kValueForNotFoundIdentifier);
hdSidExt >>= 32; // Station ID number