mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-03 03:14:17 +00:00
Extend DAB primary identifier with SCIdS.
This replaces DAB_SIDECC with DAB_SID_EXT as primary DAB identifier. Bug: 69308221 Test: it builds Change-Id: I8d3c9628e7dc8a03c5aa0c04f136e60eccaa9940
This commit is contained in:
@@ -21,6 +21,7 @@ cc_test {
|
||||
static_libs: [
|
||||
"android.hardware.broadcastradio@1.0",
|
||||
"android.hardware.broadcastradio@1.1",
|
||||
"android.hardware.broadcastradio@1.2", // common-utils-lib dependency
|
||||
"android.hardware.broadcastradio@common-utils-lib",
|
||||
"android.hardware.broadcastradio@vts-utils-lib",
|
||||
"libgmock",
|
||||
|
||||
@@ -525,6 +525,98 @@ TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
|
||||
ASSERT_FALSE(forced);
|
||||
}
|
||||
|
||||
static void verifyIdentifier(const ProgramIdentifier& id) {
|
||||
EXPECT_NE(id.type, 0u);
|
||||
auto val = id.value;
|
||||
|
||||
switch (static_cast<IdentifierType>(id.type)) {
|
||||
case IdentifierType::AMFM_FREQUENCY:
|
||||
case IdentifierType::DAB_FREQUENCY:
|
||||
case IdentifierType::DRMO_FREQUENCY:
|
||||
EXPECT_GT(val, 100u) << "Expected f > 100kHz";
|
||||
EXPECT_LT(val, 10000000u) << "Expected f < 10GHz";
|
||||
break;
|
||||
case IdentifierType::RDS_PI:
|
||||
EXPECT_GT(val, 0u);
|
||||
EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
|
||||
break;
|
||||
case IdentifierType::HD_STATION_ID_EXT: {
|
||||
auto stationId = val & 0xFFFFFFFF; // 32bit
|
||||
val >>= 32;
|
||||
auto subchannel = val & 0xF; // 4bit
|
||||
val >>= 4;
|
||||
auto freq = val & 0x3FFFF; // 18bit
|
||||
EXPECT_GT(stationId, 0u);
|
||||
EXPECT_LT(subchannel, 8u) << "Expected ch < 8";
|
||||
EXPECT_GT(freq, 100u) << "Expected f > 100kHz";
|
||||
EXPECT_LT(freq, 10000000u) << "Expected f < 10GHz";
|
||||
break;
|
||||
}
|
||||
case IdentifierType::HD_SUBCHANNEL:
|
||||
EXPECT_LT(val, 8u) << "Expected ch < 8";
|
||||
break;
|
||||
case IdentifierType::DAB_SIDECC: {
|
||||
auto sid = val & 0xFFFF; // 16bit
|
||||
val >>= 16;
|
||||
auto ecc = val & 0xFF; // 8bit
|
||||
EXPECT_NE(sid, 0u);
|
||||
EXPECT_GE(ecc, 0xA0u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
|
||||
EXPECT_LE(ecc, 0xF6u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
|
||||
break;
|
||||
}
|
||||
case IdentifierType::DAB_ENSEMBLE:
|
||||
EXPECT_GT(val, 0u);
|
||||
EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
|
||||
break;
|
||||
case IdentifierType::DAB_SCID:
|
||||
EXPECT_GT(val, 0xFu) << "Expected 12bit SCId (not 4bit SCIdS)";
|
||||
EXPECT_LE(val, 0xFFFu) << "Expected 12bit id";
|
||||
break;
|
||||
case IdentifierType::DRMO_SERVICE_ID:
|
||||
EXPECT_GT(val, 0u);
|
||||
EXPECT_LE(val, 0xFFFFFFu) << "Expected 24bit id";
|
||||
break;
|
||||
case IdentifierType::DRMO_MODULATION:
|
||||
EXPECT_GE(val, static_cast<uint32_t>(Modulation::AM));
|
||||
EXPECT_LE(val, static_cast<uint32_t>(Modulation::FM));
|
||||
break;
|
||||
case IdentifierType::SXM_SERVICE_ID:
|
||||
EXPECT_GT(val, 0u);
|
||||
EXPECT_LE(val, 0xFFFFFFFFu) << "Expected 32bit id";
|
||||
break;
|
||||
case IdentifierType::SXM_CHANNEL:
|
||||
EXPECT_LT(val, 1000u);
|
||||
break;
|
||||
case IdentifierType::VENDOR_PRIMARY_START:
|
||||
case IdentifierType::VENDOR_PRIMARY_END:
|
||||
// skip
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ProgramIdentifier format.
|
||||
*
|
||||
* Verifies that:
|
||||
* - values of ProgramIdentifier match their definitions at IdentifierType.
|
||||
*/
|
||||
TEST_P(BroadcastRadioHalTest, VerifyIdentifiersFormat) {
|
||||
if (skipped) return;
|
||||
ASSERT_TRUE(openTuner());
|
||||
|
||||
do {
|
||||
auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
|
||||
for (auto&& program : list) {
|
||||
verifyIdentifier(program.selector.primaryId);
|
||||
for (auto&& id : program.selector.secondaryIds) {
|
||||
verifyIdentifier(id);
|
||||
}
|
||||
}
|
||||
};
|
||||
getProgramList(getCb);
|
||||
} while (nextBand());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
|
||||
::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
|
||||
|
||||
|
||||
@@ -35,13 +35,13 @@ using V1_0::Band;
|
||||
using V1_0::BandConfig;
|
||||
using V1_0::Class;
|
||||
using V1_0::Direction;
|
||||
using V1_1::IdentifierType;
|
||||
using V1_1::ProgramInfo;
|
||||
using V1_1::ProgramInfoFlags;
|
||||
using V1_1::ProgramListResult;
|
||||
using V1_1::ProgramSelector;
|
||||
using V1_1::ProgramType;
|
||||
using V1_1::VendorKeyValue;
|
||||
using V1_2::IdentifierType;
|
||||
using utils::HalRevision;
|
||||
|
||||
using std::chrono::milliseconds;
|
||||
@@ -282,7 +282,7 @@ Return<Result> Tuner::tuneByProgramSelector(const ProgramSelector& sel) {
|
||||
return Result::INVALID_ARGUMENTS;
|
||||
}
|
||||
} else if (programType == ProgramType::DAB) {
|
||||
if (!utils::hasId(sel, IdentifierType::DAB_SIDECC)) return Result::INVALID_ARGUMENTS;
|
||||
if (!utils::hasId(sel, IdentifierType::DAB_SID_EXT)) return Result::INVALID_ARGUMENTS;
|
||||
} else if (programType == ProgramType::DRMO) {
|
||||
if (!utils::hasId(sel, IdentifierType::DRMO_SERVICE_ID)) return Result::INVALID_ARGUMENTS;
|
||||
} else if (programType == ProgramType::SXM) {
|
||||
|
||||
@@ -30,9 +30,9 @@ using std::vector;
|
||||
using V1_0::MetaData;
|
||||
using V1_0::MetadataKey;
|
||||
using V1_0::MetadataType;
|
||||
using V1_1::IdentifierType;
|
||||
using V1_1::ProgramInfo;
|
||||
using V1_1::VendorKeyValue;
|
||||
using V1_2::IdentifierType;
|
||||
using utils::HalRevision;
|
||||
|
||||
static MetaData createDemoBitmap(MetadataKey key, HalRevision halRev) {
|
||||
|
||||
@@ -16,8 +16,35 @@
|
||||
|
||||
package android.hardware.broadcastradio@1.2;
|
||||
|
||||
import @1.1::IdentifierType;
|
||||
import @1.1::Result;
|
||||
import @1.1::VendorKeyValue;
|
||||
|
||||
typedef @1.1::Result Result;
|
||||
typedef @1.1::VendorKeyValue VendorKeyValue;
|
||||
|
||||
enum IdentifierType : @1.1::IdentifierType {
|
||||
/**
|
||||
* 28bit compound primary identifier for DAB.
|
||||
*
|
||||
* Consists of (from the LSB):
|
||||
* - 16bit: SId;
|
||||
* - 8bit: ECC code;
|
||||
* - 4bit: SCIdS (optional).
|
||||
*
|
||||
* SCIdS (Service Component Identifier within the Service) value
|
||||
* of 0 represents the main service, while 1 and above represents
|
||||
* secondary services.
|
||||
*
|
||||
* The remaining bits should be set to zeros when writing on the chip side
|
||||
* and ignored when read.
|
||||
*
|
||||
* This identifier deprecates DAB_SIDECC and makes new primary identifier
|
||||
* for DAB. If the hal implementation detects 1.2 client (by casting
|
||||
* V1_0::ITunerCallback to V1_2::ITunerCallback), it must use DAB_SID_EXT
|
||||
* as a primary identifier for DAB program type. If the hal client detects
|
||||
* either 1.1 or 1.2 HAL, it must convert those identifiers to the
|
||||
* correct version.
|
||||
*/
|
||||
DAB_SID_EXT = SXM_CHANNEL + 1,
|
||||
};
|
||||
|
||||
@@ -295,6 +295,9 @@ TEST_P(BroadcastRadioHalTest, UnknownParameters) {
|
||||
ASSERT_EQ(0u, halResults.size());
|
||||
}
|
||||
|
||||
// TODO(b/69860743): implement VerifyIdentifiersFormat test when
|
||||
// the new program list fetching mechanism is implemented
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
|
||||
::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
|
||||
|
||||
|
||||
@@ -29,6 +29,6 @@ cc_library_static {
|
||||
],
|
||||
export_include_dirs: ["include"],
|
||||
shared_libs: [
|
||||
"android.hardware.broadcastradio@1.1",
|
||||
"android.hardware.broadcastradio@1.2",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -26,10 +26,10 @@ namespace broadcastradio {
|
||||
namespace utils {
|
||||
|
||||
using V1_0::Band;
|
||||
using V1_1::IdentifierType;
|
||||
using V1_1::ProgramIdentifier;
|
||||
using V1_1::ProgramSelector;
|
||||
using V1_1::ProgramType;
|
||||
using V1_2::IdentifierType;
|
||||
|
||||
static bool isCompatibleProgramType(const uint32_t ia, const uint32_t ib) {
|
||||
auto a = static_cast<ProgramType>(ia);
|
||||
@@ -88,7 +88,7 @@ bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
|
||||
|
||||
return haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
|
||||
case ProgramType::DAB:
|
||||
return haveEqualIds(a, b, IdentifierType::DAB_SIDECC);
|
||||
return haveEqualIds(a, b, IdentifierType::DAB_SID_EXT);
|
||||
case ProgramType::DRMO:
|
||||
return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
|
||||
case ProgramType::SXM:
|
||||
@@ -126,23 +126,50 @@ bool isFm(const Band band) {
|
||||
return band == Band::FM || band == Band::FM_HD;
|
||||
}
|
||||
|
||||
bool hasId(const ProgramSelector& sel, const IdentifierType type) {
|
||||
static bool maybeGetId(const ProgramSelector& sel, const IdentifierType type, uint64_t* val) {
|
||||
auto itype = static_cast<uint32_t>(type);
|
||||
if (sel.primaryId.type == itype) return true;
|
||||
// not optimal, but we don't care in default impl
|
||||
for (auto&& id : sel.secondaryIds) {
|
||||
if (id.type == itype) return true;
|
||||
auto itypeAlt = itype;
|
||||
if (type == IdentifierType::DAB_SIDECC) {
|
||||
itypeAlt = static_cast<uint32_t>(IdentifierType::DAB_SID_EXT);
|
||||
}
|
||||
return false;
|
||||
if (type == IdentifierType::DAB_SID_EXT) {
|
||||
itypeAlt = static_cast<uint32_t>(IdentifierType::DAB_SIDECC);
|
||||
}
|
||||
|
||||
if (sel.primaryId.type == itype || sel.primaryId.type == itypeAlt) {
|
||||
if (val) *val = sel.primaryId.value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// not optimal, but we don't care in default impl
|
||||
bool gotAlt = false;
|
||||
for (auto&& id : sel.secondaryIds) {
|
||||
if (id.type == itype) {
|
||||
if (val) *val = id.value;
|
||||
return true;
|
||||
}
|
||||
// alternative identifier is a backup, we prefer original value
|
||||
if (id.type == itypeAlt) {
|
||||
if (val) *val = id.value;
|
||||
gotAlt = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return gotAlt;
|
||||
}
|
||||
|
||||
bool hasId(const ProgramSelector& sel, const IdentifierType type) {
|
||||
return maybeGetId(sel, type, nullptr);
|
||||
}
|
||||
|
||||
uint64_t getId(const ProgramSelector& sel, const IdentifierType type) {
|
||||
auto itype = static_cast<uint32_t>(type);
|
||||
if (sel.primaryId.type == itype) return sel.primaryId.value;
|
||||
// not optimal, but we don't care in default impl
|
||||
for (auto&& id : sel.secondaryIds) {
|
||||
if (id.type == itype) return id.value;
|
||||
uint64_t val;
|
||||
|
||||
if (maybeGetId(sel, type, &val)) {
|
||||
return val;
|
||||
}
|
||||
|
||||
ALOGW("Identifier %s not found", toString(type).c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#ifndef ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_H
|
||||
#define ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_H
|
||||
|
||||
#include <android/hardware/broadcastradio/1.1/types.h>
|
||||
#include <android/hardware/broadcastradio/1.2/types.h>
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
@@ -50,21 +50,21 @@ bool isAmFm(const V1_1::ProgramType type);
|
||||
bool isAm(const V1_0::Band band);
|
||||
bool isFm(const V1_0::Band band);
|
||||
|
||||
bool hasId(const V1_1::ProgramSelector& sel, const V1_1::IdentifierType type);
|
||||
bool hasId(const V1_1::ProgramSelector& sel, const V1_2::IdentifierType type);
|
||||
|
||||
/**
|
||||
* Returns ID (either primary or secondary) for a given program selector.
|
||||
*
|
||||
* If the selector does not contain given type, returns 0 and emits a warning.
|
||||
*/
|
||||
uint64_t getId(const V1_1::ProgramSelector& sel, const V1_1::IdentifierType type);
|
||||
uint64_t getId(const V1_1::ProgramSelector& sel, const V1_2::IdentifierType type);
|
||||
|
||||
/**
|
||||
* Returns ID (either primary or secondary) for a given program selector.
|
||||
*
|
||||
* If the selector does not contain given type, returns default value.
|
||||
*/
|
||||
uint64_t getId(const V1_1::ProgramSelector& sel, const V1_1::IdentifierType type, uint64_t defval);
|
||||
uint64_t getId(const V1_1::ProgramSelector& sel, const V1_2::IdentifierType type, uint64_t defval);
|
||||
|
||||
V1_1::ProgramSelector make_selector(V1_0::Band band, uint32_t channel, uint32_t subChannel = 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user