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
This commit is contained in:
Weilin Xu
2023-11-07 20:07:23 -08:00
parent 7991996514
commit 90e39f542d
6 changed files with 110 additions and 36 deletions

View File

@@ -66,12 +66,7 @@ Properties initProperties(const VirtualRadio& virtualRadio) {
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 @@ 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<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) {

View File

@@ -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) {

View File

@@ -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::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<VirtualProgram>& initialList)
@@ -62,6 +64,20 @@ bool VirtualRadio::getProgram(const ProgramSelector& selector, VirtualProgram* p
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 @@ 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;

View File

@@ -36,6 +36,7 @@ class VirtualRadio final {
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();

View File

@@ -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);

View File

@@ -489,6 +489,21 @@ IdentifierType getType(int typeAsInt) {
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