summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/radio/ProgramSelector.java87
-rw-r--r--core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramListTest.java18
-rw-r--r--core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramSelectorTest.java40
-rw-r--r--core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioManagerTest.java18
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java34
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java159
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java28
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java13
-rw-r--r--services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java88
-rw-r--r--services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java6
-rw-r--r--services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java14
-rw-r--r--services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java7
12 files changed, 420 insertions, 92 deletions
diff --git a/core/java/android/hardware/radio/ProgramSelector.java b/core/java/android/hardware/radio/ProgramSelector.java
index 7faa285a8fee..727716e67f28 100644
--- a/core/java/android/hardware/radio/ProgramSelector.java
+++ b/core/java/android/hardware/radio/ProgramSelector.java
@@ -65,12 +65,12 @@ public final class ProgramSelector implements Parcelable {
*/
@Deprecated
public static final int PROGRAM_TYPE_INVALID = 0;
- /** Analogue AM radio (with or without RDS).
+ /** Analog AM radio (with or without RDS).
* @deprecated use {@link ProgramIdentifier} instead
*/
@Deprecated
public static final int PROGRAM_TYPE_AM = 1;
- /** analogue FM radio (with or without RDS).
+ /** analog FM radio (with or without RDS).
* @deprecated use {@link ProgramIdentifier} instead
*/
@Deprecated
@@ -125,25 +125,50 @@ public final class ProgramSelector implements Parcelable {
public @interface ProgramType {}
public static final int IDENTIFIER_TYPE_INVALID = 0;
- /** kHz */
+ /**
+ * Primary identifier for analog (without RDS) AM/FM stations:
+ * frequency in kHz.
+ *
+ * <p>This identifier also contains band information:
+ * <li>
+ * <ul><500kHz: AM LW.
+ * <ul>500kHz - 1705kHz: AM MW.
+ * <ul>1.71MHz - 30MHz: AM SW.
+ * <ul>>60MHz: FM.
+ * </li>
+ */
public static final int IDENTIFIER_TYPE_AMFM_FREQUENCY = 1;
- /** 16bit */
+ /**
+ * 16bit primary identifier for FM RDS station.
+ */
public static final int IDENTIFIER_TYPE_RDS_PI = 2;
/**
* 64bit compound primary identifier for HD Radio.
*
- * Consists of (from the LSB):
- * - 32bit: Station ID number;
- * - 4bit: HD_SUBCHANNEL;
- * - 18bit: AMFM_FREQUENCY.
- * The remaining bits should be set to zeros when writing on the chip side
+ * <p>Consists of (from the LSB):
+ * <li>
+ * <ul>132bit: Station ID number.
+ * <ul>14bit: HD_SUBCHANNEL.
+ * <ul>18bit: AMFM_FREQUENCY.
+ * </li>
+ *
+ * <p>While station ID number should be unique globally, it sometimes gets
+ * abused by broadcasters (i.e. not being set at all). To ensure local
+ * uniqueness, AMFM_FREQUENCY_KHZ was added here. Global uniqueness is
+ * a best-effort - see {@link IDENTIFIER_TYPE_HD_STATION_NAME}.
+ *
+ * <p>HD Radio subchannel is a value in range of 0-7.
+ * This index is 0-based (where 0 is MPS and 1..7 are SPS),
+ * as opposed to HD Radio standard (where it's 1-based).
+ *
+ * <p>The remaining bits should be set to zeros when writing on the chip side
* and ignored when read.
*/
public static final int IDENTIFIER_TYPE_HD_STATION_ID_EXT = 3;
/**
- * HD Radio subchannel - a value of range 0-7.
+ * HD Radio subchannel - a value in range of 0-7.
*
- * The subchannel index is 0-based (where 0 is MPS and 1..7 are SPS),
+ * <p>The subchannel index is 0-based (where 0 is MPS and 1..7 are SPS),
* as opposed to HD Radio standard (where it's 1-based).
*
* @deprecated use IDENTIFIER_TYPE_HD_STATION_ID_EXT instead
@@ -153,16 +178,16 @@ public final class ProgramSelector implements Parcelable {
/**
* 64bit additional identifier for HD Radio.
*
- * Due to Station ID abuse, some HD_STATION_ID_EXT identifiers may be not
+ * <p>Due to Station ID abuse, some HD_STATION_ID_EXT identifiers may be not
* globally unique. To provide a best-effort solution, a short version of
* station name may be carried as additional identifier and may be used
* by the tuner hardware to double-check tuning.
*
- * The name is limited to the first 8 A-Z0-9 characters (lowercase letters
- * must be converted to uppercase). Encoded in little-endian ASCII:
- * the first character of the name is the LSB.
+ * <p>The name is limited to the first 8 A-Z0-9 characters (lowercase
+ * letters must be converted to uppercase). Encoded in little-endian
+ * ASCII: the first character of the name is the LSB.
*
- * For example: "Abc" is encoded as 0x434241.
+ * <p>For example: "Abc" is encoded as 0x434241.
*/
public static final int IDENTIFIER_TYPE_HD_STATION_NAME = 10004;
/**
@@ -175,17 +200,19 @@ public final class ProgramSelector implements Parcelable {
/**
* 28bit compound primary identifier for Digital Audio Broadcasting.
*
- * Consists of (from the LSB):
- * - 16bit: SId;
- * - 8bit: ECC code;
- * - 4bit: SCIdS.
+ * <p>Consists of (from the LSB):
+ * <li>
+ * <ul>16bit: SId.
+ * <ul>8bit: ECC code.
+ * <ul>4bit: SCIdS.
+ * </li>
*
- * SCIdS (Service Component Identifier within the Service) value
+ * <p>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.
+ * <p>The remaining bits should be set to zeros when writing on the chip
+ * side and ignored when read.
*
* @deprecated use {@link #IDENTIFIER_TYPE_DAB_DMB_SID_EXT} instead
*/
@@ -197,7 +224,9 @@ public final class ProgramSelector implements Parcelable {
public static final int IDENTIFIER_TYPE_DAB_SCID = 7;
/** kHz */
public static final int IDENTIFIER_TYPE_DAB_FREQUENCY = 8;
- /** 24bit */
+ /**
+ * 24bit primary identifier for Digital Radio Mondiale.
+ */
public static final int IDENTIFIER_TYPE_DRMO_SERVICE_ID = 9;
/** kHz */
public static final int IDENTIFIER_TYPE_DRMO_FREQUENCY = 10;
@@ -207,7 +236,9 @@ public final class ProgramSelector implements Parcelable {
*/
@Deprecated
public static final int IDENTIFIER_TYPE_DRMO_MODULATION = 11;
- /** 32bit */
+ /**
+ * 32bit primary identifier for SiriusXM Satellite Radio.
+ */
public static final int IDENTIFIER_TYPE_SXM_SERVICE_ID = 12;
/** 0-999 range */
public static final int IDENTIFIER_TYPE_SXM_CHANNEL = 13;
@@ -224,15 +255,15 @@ public final class ProgramSelector implements Parcelable {
* 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.
+ * <p>The remaining bits should be set to zeros when writing on the chip
+ * side and ignored when read.
*/
public static final int IDENTIFIER_TYPE_DAB_DMB_SID_EXT = 14;
/**
* Primary identifier for vendor-specific radio technology.
* The value format is determined by a vendor.
*
- * It must not be used in any other programType than corresponding VENDOR
+ * <p>It must not be used in any other programType than corresponding VENDOR
* type between VENDOR_START and VENDOR_END (eg. identifier type 1015 must
* not be used in any program type other than 1015).
*/
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramListTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramListTest.java
index 87f91fa436ed..9e99b7c99e0d 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramListTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramListTest.java
@@ -72,9 +72,9 @@ public final class ProgramListTest {
/* value= */ 94300);
private static final ProgramSelector.Identifier RDS_IDENTIFIER =
new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI, 15019);
- private static final ProgramSelector.Identifier DAB_SID_EXT_IDENTIFIER =
- new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT,
- /* value= */ 0x10000111);
+ private static final ProgramSelector.Identifier DAB_DMB_SID_EXT_IDENTIFIER =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT,
+ /* value= */ 0xA000000111L);
private static final ProgramSelector.Identifier DAB_ENSEMBLE_IDENTIFIER =
new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE,
/* value= */ 0x1013);
@@ -89,7 +89,7 @@ public final class ProgramListTest {
private static final ProgramList.Chunk FM_RDS_ADD_CHUNK = new ProgramList.Chunk(IS_PURGE,
IS_COMPLETE, Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO),
- Set.of(DAB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
+ Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
private static final ProgramList.Chunk FM_ADD_INCOMPLETE_CHUNK = new ProgramList.Chunk(IS_PURGE,
/* complete= */ false, Set.of(FM_PROGRAM_INFO), new ArraySet<>());
private static final ProgramList.Filter TEST_FILTER = new ProgramList.Filter(
@@ -216,7 +216,7 @@ public final class ProgramListTest {
public void isPurge_forChunk() {
ProgramList.Chunk chunk = new ProgramList.Chunk(IS_PURGE, IS_COMPLETE,
Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO),
- Set.of(DAB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
+ Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
assertWithMessage("Puring chunk").that(chunk.isPurge()).isEqualTo(IS_PURGE);
}
@@ -225,7 +225,7 @@ public final class ProgramListTest {
public void isComplete_forChunk() {
ProgramList.Chunk chunk = new ProgramList.Chunk(IS_PURGE, IS_COMPLETE,
Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO),
- Set.of(DAB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
+ Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
assertWithMessage("Complete chunk").that(chunk.isComplete()).isEqualTo(IS_COMPLETE);
}
@@ -234,7 +234,7 @@ public final class ProgramListTest {
public void getModified_forChunk() {
ProgramList.Chunk chunk = new ProgramList.Chunk(IS_PURGE, IS_COMPLETE,
Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO),
- Set.of(DAB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
+ Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
assertWithMessage("Modified program info in chunk")
.that(chunk.getModified()).containsExactly(FM_PROGRAM_INFO, RDS_PROGRAM_INFO);
@@ -244,10 +244,10 @@ public final class ProgramListTest {
public void getRemoved_forChunk() {
ProgramList.Chunk chunk = new ProgramList.Chunk(IS_PURGE, IS_COMPLETE,
Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO),
- Set.of(DAB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
+ Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER));
assertWithMessage("Removed program identifiers in chunk").that(chunk.getRemoved())
- .containsExactly(DAB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER);
+ .containsExactly(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER);
}
@Test
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramSelectorTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramSelectorTest.java
index 5bd018bea1d1..9399907cf33c 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramSelectorTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/ProgramSelectorTest.java
@@ -36,18 +36,18 @@ public final class ProgramSelectorTest {
private static final long AM_FREQUENCY = 700;
private static final ProgramSelector.Identifier FM_IDENTIFIER = new ProgramSelector.Identifier(
ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, FM_FREQUENCY);
- private static final ProgramSelector.Identifier DAB_SID_EXT_IDENTIFIER_1 =
- new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT,
- /* value= */ 0x1000011);
- private static final ProgramSelector.Identifier DAB_SID_EXT_IDENTIFIER_2 =
- new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT,
- /* value= */ 0x10000112);
+ private static final ProgramSelector.Identifier DAB_DMB_SID_EXT_IDENTIFIER_1 =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT,
+ /* value= */ 0xA000000111L);
+ private static final ProgramSelector.Identifier DAB_DMB_SID_EXT_IDENTIFIER_2 =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT,
+ /* value= */ 0xA000000112L);
private static final ProgramSelector.Identifier DAB_ENSEMBLE_IDENTIFIER =
new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE,
/* value= */ 0x1001);
private static final ProgramSelector.Identifier DAB_FREQUENCY_IDENTIFIER =
new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY,
- /* value= */ 94500);
+ /* value= */ 220352);
@Test
public void getType_forIdentifier() {
@@ -80,13 +80,13 @@ public final class ProgramSelectorTest {
@Test
public void equals_withDifferentTypesForIdentifiers_returnsFalse() {
assertWithMessage("Identifier with different identifier type")
- .that(FM_IDENTIFIER).isNotEqualTo(DAB_SID_EXT_IDENTIFIER_1);
+ .that(FM_IDENTIFIER).isNotEqualTo(DAB_DMB_SID_EXT_IDENTIFIER_1);
}
@Test
public void equals_withDifferentValuesForIdentifiers_returnsFalse() {
assertWithMessage("Identifier with different identifier value")
- .that(DAB_SID_EXT_IDENTIFIER_2).isNotEqualTo(DAB_SID_EXT_IDENTIFIER_1);
+ .that(DAB_DMB_SID_EXT_IDENTIFIER_2).isNotEqualTo(DAB_DMB_SID_EXT_IDENTIFIER_1);
}
@Test
@@ -168,19 +168,19 @@ public final class ProgramSelectorTest {
@Test
public void getFirstId_withIdInSelector() {
ProgramSelector.Identifier[] secondaryIds = new ProgramSelector.Identifier[]{
- DAB_ENSEMBLE_IDENTIFIER, DAB_SID_EXT_IDENTIFIER_2, DAB_FREQUENCY_IDENTIFIER};
+ DAB_ENSEMBLE_IDENTIFIER, DAB_DMB_SID_EXT_IDENTIFIER_2, DAB_FREQUENCY_IDENTIFIER};
ProgramSelector selector = getDabSelector(secondaryIds, /* vendorIds= */ null);
- long firstIdValue = selector.getFirstId(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT);
+ long firstIdValue = selector.getFirstId(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT);
assertWithMessage("Value of the first DAB_SID_EXT identifier")
- .that(firstIdValue).isEqualTo(DAB_SID_EXT_IDENTIFIER_1.getValue());
+ .that(firstIdValue).isEqualTo(DAB_DMB_SID_EXT_IDENTIFIER_1.getValue());
}
@Test
public void getFirstId_withIdNotInSelector() {
ProgramSelector.Identifier[] secondaryIds = new ProgramSelector.Identifier[]{
- DAB_ENSEMBLE_IDENTIFIER, DAB_SID_EXT_IDENTIFIER_2};
+ DAB_ENSEMBLE_IDENTIFIER, DAB_DMB_SID_EXT_IDENTIFIER_2};
ProgramSelector selector = getDabSelector(secondaryIds, /* vendorIds= */ null);
int idType = ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY;
@@ -195,13 +195,13 @@ public final class ProgramSelectorTest {
@Test
public void getAllIds_withIdInSelector() {
ProgramSelector.Identifier[] secondaryIds = new ProgramSelector.Identifier[]{
- DAB_ENSEMBLE_IDENTIFIER, DAB_SID_EXT_IDENTIFIER_2, DAB_FREQUENCY_IDENTIFIER};
+ DAB_ENSEMBLE_IDENTIFIER, DAB_DMB_SID_EXT_IDENTIFIER_2, DAB_FREQUENCY_IDENTIFIER};
ProgramSelector.Identifier[] allIdsExpected =
- {DAB_SID_EXT_IDENTIFIER_1, DAB_SID_EXT_IDENTIFIER_2};
+ {DAB_DMB_SID_EXT_IDENTIFIER_1, DAB_DMB_SID_EXT_IDENTIFIER_2};
ProgramSelector selector = getDabSelector(secondaryIds, /* vendorIds= */ null);
ProgramSelector.Identifier[] allIds =
- selector.getAllIds(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT);
+ selector.getAllIds(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT);
assertWithMessage("All DAB_SID_EXT identifiers in selector")
.that(allIds).isEqualTo(allIdsExpected);
@@ -244,14 +244,14 @@ public final class ProgramSelectorTest {
@Test
public void withSecondaryPreferred() {
ProgramSelector.Identifier[] secondaryIds = new ProgramSelector.Identifier[]{
- DAB_ENSEMBLE_IDENTIFIER, DAB_SID_EXT_IDENTIFIER_2, DAB_FREQUENCY_IDENTIFIER};
+ DAB_ENSEMBLE_IDENTIFIER, DAB_DMB_SID_EXT_IDENTIFIER_2, DAB_FREQUENCY_IDENTIFIER};
long[] vendorIdsExpected = {12345, 678};
ProgramSelector selector = getDabSelector(secondaryIds, vendorIdsExpected);
ProgramSelector.Identifier[] secondaryIdsExpected = new ProgramSelector.Identifier[]{
- DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER, DAB_SID_EXT_IDENTIFIER_1};
+ DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER, DAB_DMB_SID_EXT_IDENTIFIER_1};
ProgramSelector selectorPreferred =
- selector.withSecondaryPreferred(DAB_SID_EXT_IDENTIFIER_1);
+ selector.withSecondaryPreferred(DAB_DMB_SID_EXT_IDENTIFIER_1);
assertWithMessage("Program type")
.that(selectorPreferred.getProgramType()).isEqualTo(selector.getProgramType());
@@ -458,7 +458,7 @@ public final class ProgramSelectorTest {
private ProgramSelector getDabSelector(@Nullable ProgramSelector.Identifier[] secondaryIds,
@Nullable long[] vendorIds) {
- return new ProgramSelector(DAB_PROGRAM_TYPE, DAB_SID_EXT_IDENTIFIER_1, secondaryIds,
+ return new ProgramSelector(DAB_PROGRAM_TYPE, DAB_DMB_SID_EXT_IDENTIFIER_1, secondaryIds,
vendorIds);
}
}
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioManagerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioManagerTest.java
index 03742eb93a3b..7dd13394e48d 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioManagerTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/unittests/RadioManagerTest.java
@@ -105,17 +105,17 @@ public final class RadioManagerTest {
private static final int INFO_FLAGS = 0b110001;
private static final int SIGNAL_QUALITY = 2;
private static final ProgramSelector.Identifier DAB_SID_EXT_IDENTIFIER =
- new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT,
- /* value= */ 0x10000111);
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT,
+ /* value= */ 0xA000000111L);
private static final ProgramSelector.Identifier DAB_SID_EXT_IDENTIFIER_RELATED =
- new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT,
- /* value= */ 0x10000113);
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT,
+ /* value= */ 0xA000000113L);
private static final ProgramSelector.Identifier DAB_ENSEMBLE_IDENTIFIER =
new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE,
/* value= */ 0x1013);
private static final ProgramSelector.Identifier DAB_FREQUENCY_IDENTIFIER =
new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY,
- /* value= */ 95500);
+ /* value= */ 220352);
private static final ProgramSelector DAB_SELECTOR =
new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB, DAB_SID_EXT_IDENTIFIER,
new ProgramSelector.Identifier[]{
@@ -859,13 +859,13 @@ public final class RadioManagerTest {
@Test
public void getLogicallyTunedTo_forProgramInfo() {
assertWithMessage("Identifier logically tuned to in DAB program info")
- .that(DAB_PROGRAM_INFO.getLogicallyTunedTo()).isEqualTo(DAB_FREQUENCY_IDENTIFIER);
+ .that(DAB_PROGRAM_INFO.getLogicallyTunedTo()).isEqualTo(DAB_SID_EXT_IDENTIFIER);
}
@Test
public void getPhysicallyTunedTo_forProgramInfo() {
assertWithMessage("Identifier physically tuned to DAB program info")
- .that(DAB_PROGRAM_INFO.getPhysicallyTunedTo()).isEqualTo(DAB_SID_EXT_IDENTIFIER);
+ .that(DAB_PROGRAM_INFO.getPhysicallyTunedTo()).isEqualTo(DAB_FREQUENCY_IDENTIFIER);
}
@Test
@@ -1104,8 +1104,8 @@ public final class RadioManagerTest {
}
private static RadioManager.ProgramInfo createDabProgramInfo(ProgramSelector selector) {
- return new RadioManager.ProgramInfo(selector, DAB_FREQUENCY_IDENTIFIER,
- DAB_SID_EXT_IDENTIFIER, Arrays.asList(DAB_SID_EXT_IDENTIFIER_RELATED), INFO_FLAGS,
+ return new RadioManager.ProgramInfo(selector, DAB_SID_EXT_IDENTIFIER,
+ DAB_FREQUENCY_IDENTIFIER, Arrays.asList(DAB_SID_EXT_IDENTIFIER_RELATED), INFO_FLAGS,
SIGNAL_QUALITY, METADATA, /* vendorInfo= */ null);
}
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
index a4212180d0b5..3037f345b5a3 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
@@ -54,6 +54,13 @@ final class AidlTestUtils {
return makeProgramInfo(selector, signalQuality);
}
+ static ProgramIdentifier makeHalIdentifier(@IdentifierType int type, long value) {
+ ProgramIdentifier halDabId = new ProgramIdentifier();
+ halDabId.type = type;
+ halDabId.value = value;
+ return halDabId;
+ }
+
static ProgramSelector makeFmSelector(long freq) {
return makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM,
new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY,
@@ -67,15 +74,17 @@ final class AidlTestUtils {
}
static android.hardware.broadcastradio.ProgramSelector makeHalFmSelector(int freq) {
- ProgramIdentifier halId = new ProgramIdentifier();
- halId.type = IdentifierType.AMFM_FREQUENCY_KHZ;
- halId.value = freq;
+ ProgramIdentifier halId = makeHalIdentifier(IdentifierType.AMFM_FREQUENCY_KHZ, freq);
+ return makeHalSelector(halId, /* secondaryIds= */ new ProgramIdentifier[0]);
+ }
- android.hardware.broadcastradio.ProgramSelector halSelector =
+ static android.hardware.broadcastradio.ProgramSelector makeHalSelector(
+ ProgramIdentifier primaryId, ProgramIdentifier[] secondaryIds) {
+ android.hardware.broadcastradio.ProgramSelector hwSelector =
new android.hardware.broadcastradio.ProgramSelector();
- halSelector.primaryId = halId;
- halSelector.secondaryIds = new ProgramIdentifier[0];
- return halSelector;
+ hwSelector.primaryId = primaryId;
+ hwSelector.secondaryIds = secondaryIds;
+ return hwSelector;
}
static ProgramInfo programInfoToHalProgramInfo(RadioManager.ProgramInfo info) {
@@ -95,10 +104,17 @@ final class AidlTestUtils {
static ProgramInfo makeHalProgramInfo(
android.hardware.broadcastradio.ProgramSelector hwSel, int hwSignalQuality) {
+ return makeHalProgramInfo(hwSel, hwSel.primaryId, hwSel.primaryId, hwSignalQuality);
+ }
+
+ static ProgramInfo makeHalProgramInfo(
+ android.hardware.broadcastradio.ProgramSelector hwSel,
+ ProgramIdentifier logicallyTunedTo, ProgramIdentifier physicallyTunedTo,
+ int hwSignalQuality) {
ProgramInfo hwInfo = new ProgramInfo();
hwInfo.selector = hwSel;
- hwInfo.logicallyTunedTo = hwSel.primaryId;
- hwInfo.physicallyTunedTo = hwSel.primaryId;
+ hwInfo.logicallyTunedTo = logicallyTunedTo;
+ hwInfo.physicallyTunedTo = physicallyTunedTo;
hwInfo.signalQuality = hwSignalQuality;
hwInfo.relatedContent = new ProgramIdentifier[]{};
hwInfo.metadata = new Metadata[]{};
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
index a1cebb630aac..6604d2aea7c1 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
@@ -20,6 +20,8 @@ import android.hardware.broadcastradio.AmFmBandRange;
import android.hardware.broadcastradio.AmFmRegionConfig;
import android.hardware.broadcastradio.DabTableEntry;
import android.hardware.broadcastradio.IdentifierType;
+import android.hardware.broadcastradio.ProgramIdentifier;
+import android.hardware.broadcastradio.ProgramInfo;
import android.hardware.broadcastradio.Properties;
import android.hardware.broadcastradio.VendorKeyValue;
import android.hardware.radio.Announcement;
@@ -57,6 +59,27 @@ public final class ConversionUtilsTest {
private static final String TEST_VERSION = "versionMock";
private static final String TEST_SERIAL = "serialMock";
+ private static final int TEST_SIGNAL_QUALITY = 1;
+ private static final long TEST_DAB_DMB_SID_EXT_VALUE = 0xA000000111L;
+ private static final long TEST_DAB_ENSEMBLE_VALUE = 0x1001;
+ private static final long TEST_DAB_FREQUENCY_VALUE = 220352;
+ private static final ProgramSelector.Identifier TEST_DAB_SID_EXT_ID =
+ new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT, TEST_DAB_DMB_SID_EXT_VALUE);
+ private static final ProgramSelector.Identifier TEST_DAB_ENSEMBLE_ID =
+ new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, TEST_DAB_ENSEMBLE_VALUE);
+ private static final ProgramSelector.Identifier TEST_DAB_FREQUENCY_ID =
+ new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, TEST_DAB_FREQUENCY_VALUE);
+ private static final ProgramIdentifier TEST_HAL_DAB_SID_EXT_ID =
+ AidlTestUtils.makeHalIdentifier(IdentifierType.DAB_SID_EXT, TEST_DAB_DMB_SID_EXT_VALUE);
+ private static final ProgramIdentifier TEST_HAL_DAB_ENSEMBLE_ID =
+ AidlTestUtils.makeHalIdentifier(IdentifierType.DAB_ENSEMBLE, TEST_DAB_ENSEMBLE_VALUE);
+ private static final ProgramIdentifier TEST_HAL_DAB_FREQUENCY_ID =
+ AidlTestUtils.makeHalIdentifier(IdentifierType.DAB_FREQUENCY_KHZ,
+ TEST_DAB_FREQUENCY_VALUE);
+
private static final int TEST_ENABLED_TYPE = Announcement.TYPE_EMERGENCY;
private static final int TEST_ANNOUNCEMENT_FREQUENCY = FM_LOWER_LIMIT + FM_SPACING;
@@ -159,6 +182,142 @@ public final class ConversionUtilsTest {
}
@Test
+ public void identifierToHalProgramIdentifier_withDabId() {
+ ProgramIdentifier halDabId =
+ ConversionUtils.identifierToHalProgramIdentifier(TEST_DAB_SID_EXT_ID);
+
+ expect.withMessage("Converted HAL DAB identifier").that(halDabId)
+ .isEqualTo(TEST_HAL_DAB_SID_EXT_ID);
+ }
+
+ @Test
+ public void identifierFromHalProgramIdentifier_withDabId() {
+ ProgramSelector.Identifier dabId =
+ ConversionUtils.identifierFromHalProgramIdentifier(TEST_HAL_DAB_SID_EXT_ID);
+
+ expect.withMessage("Converted DAB identifier").that(dabId).isEqualTo(TEST_DAB_SID_EXT_ID);
+ }
+
+ @Test
+ public void programSelectorToHalProgramSelector_withValidSelector() {
+ ProgramSelector dabSelector = new ProgramSelector(
+ ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_EXT_ID,
+ new ProgramSelector.Identifier[]{TEST_DAB_ENSEMBLE_ID, TEST_DAB_FREQUENCY_ID},
+ new long[0]);
+
+ android.hardware.broadcastradio.ProgramSelector halDabSelector =
+ ConversionUtils.programSelectorToHalProgramSelector(dabSelector);
+
+ expect.withMessage("Primary identifier of converted HAL DAB selector")
+ .that(halDabSelector.primaryId).isEqualTo(TEST_HAL_DAB_SID_EXT_ID);
+ expect.withMessage("Secondary identifiers of converted HAL DAB selector")
+ .that(halDabSelector.secondaryIds).asList()
+ .containsExactly(TEST_HAL_DAB_FREQUENCY_ID, TEST_HAL_DAB_ENSEMBLE_ID);
+ }
+
+ @Test
+ public void programSelectorToHalProgramSelector_withInvalidDabSelector_returnsNull() {
+ ProgramSelector invalidDbSelector = new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB,
+ TEST_DAB_SID_EXT_ID,
+ new ProgramSelector.Identifier[0],
+ new long[0]);
+
+ android.hardware.broadcastradio.ProgramSelector invalidHalDabSelector =
+ ConversionUtils.programSelectorToHalProgramSelector(invalidDbSelector);
+
+ expect.withMessage("Invalid HAL DAB selector without required secondary ids")
+ .that(invalidHalDabSelector).isNull();
+ }
+
+ @Test
+ public void programSelectorFromHalProgramSelector_withValidSelector() {
+ android.hardware.broadcastradio.ProgramSelector halDabSelector =
+ AidlTestUtils.makeHalSelector(TEST_HAL_DAB_SID_EXT_ID, new ProgramIdentifier[]{
+ TEST_HAL_DAB_ENSEMBLE_ID, TEST_HAL_DAB_FREQUENCY_ID});
+
+ ProgramSelector dabSelector =
+ ConversionUtils.programSelectorFromHalProgramSelector(halDabSelector);
+
+ expect.withMessage("Primary identifier of converted DAB selector")
+ .that(dabSelector.getPrimaryId()).isEqualTo(TEST_DAB_SID_EXT_ID);
+ expect.withMessage("Secondary identifiers of converted DAB selector")
+ .that(dabSelector.getSecondaryIds()).asList()
+ .containsExactly(TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID);
+ }
+
+ @Test
+ public void programSelectorFromHalProgramSelector_withInvalidSelector_returnsNull() {
+ android.hardware.broadcastradio.ProgramSelector invalidHalDabSelector =
+ AidlTestUtils.makeHalSelector(TEST_HAL_DAB_SID_EXT_ID, new ProgramIdentifier[]{});
+
+ ProgramSelector invalidDabSelector =
+ ConversionUtils.programSelectorFromHalProgramSelector(invalidHalDabSelector);
+
+ expect.withMessage("Invalid DAB selector without required secondary ids")
+ .that(invalidDabSelector).isNull();
+ }
+
+ @Test
+ public void programInfoFromHalProgramInfo_withValidProgramInfo() {
+ android.hardware.broadcastradio.ProgramSelector halDabSelector =
+ AidlTestUtils.makeHalSelector(TEST_HAL_DAB_SID_EXT_ID, new ProgramIdentifier[]{
+ TEST_HAL_DAB_ENSEMBLE_ID, TEST_HAL_DAB_FREQUENCY_ID});
+ ProgramInfo halProgramInfo = AidlTestUtils.makeHalProgramInfo(halDabSelector,
+ TEST_HAL_DAB_SID_EXT_ID, TEST_HAL_DAB_FREQUENCY_ID, TEST_SIGNAL_QUALITY);
+
+ RadioManager.ProgramInfo programInfo =
+ ConversionUtils.programInfoFromHalProgramInfo(halProgramInfo);
+
+ expect.withMessage("Primary id of selector of converted program info")
+ .that(programInfo.getSelector().getPrimaryId()).isEqualTo(TEST_DAB_SID_EXT_ID);
+ expect.withMessage("Secondary id of selector of converted program info")
+ .that(programInfo.getSelector().getSecondaryIds()).asList()
+ .containsExactly(TEST_DAB_ENSEMBLE_ID, TEST_DAB_FREQUENCY_ID);
+ expect.withMessage("Logically tuned identifier of converted program info")
+ .that(programInfo.getLogicallyTunedTo()).isEqualTo(TEST_DAB_SID_EXT_ID);
+ expect.withMessage("Physically tuned identifier of converted program info")
+ .that(programInfo.getPhysicallyTunedTo()).isEqualTo(TEST_DAB_FREQUENCY_ID);
+ expect.withMessage("Signal quality of converted program info")
+ .that(programInfo.getSignalStrength()).isEqualTo(TEST_SIGNAL_QUALITY);
+ }
+
+ @Test
+ public void programInfoFromHalProgramInfo_withInvalidDabProgramInfo() {
+ android.hardware.broadcastradio.ProgramSelector invalidHalDabSelector =
+ AidlTestUtils.makeHalSelector(TEST_HAL_DAB_SID_EXT_ID,
+ new ProgramIdentifier[]{TEST_HAL_DAB_ENSEMBLE_ID, TEST_HAL_DAB_FREQUENCY_ID});
+ ProgramInfo halProgramInfo = AidlTestUtils.makeHalProgramInfo(invalidHalDabSelector,
+ TEST_HAL_DAB_SID_EXT_ID, TEST_HAL_DAB_ENSEMBLE_ID, TEST_SIGNAL_QUALITY);
+
+ RadioManager.ProgramInfo programInfo =
+ ConversionUtils.programInfoFromHalProgramInfo(halProgramInfo);
+
+ expect.withMessage("Invalid DAB program info with incorrect type of physically tuned to id")
+ .that(programInfo).isNull();
+ }
+
+ @Test
+ public void programSelectorMeetsSdkVersionRequirement_withLowerVersionId_returnsFalse() {
+ ProgramSelector dabSelector = new ProgramSelector(
+ ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_EXT_ID,
+ new ProgramSelector.Identifier[]{TEST_DAB_ENSEMBLE_ID, TEST_DAB_FREQUENCY_ID},
+ new long[0]);
+
+ expect.withMessage("Selector %s not meeting required SDK version", dabSelector)
+ .that(ConversionUtils.programSelectorMeetsSdkVersionRequirement(dabSelector,
+ Build.VERSION_CODES.TIRAMISU)).isFalse();
+ }
+
+ @Test
+ public void programSelectorMeetsSdkVersionRequirement_withRequiredVersionId_returnsTrue() {
+ ProgramSelector fmSelector = AidlTestUtils.makeFmSelector(/* freq= */ 97100);
+
+ expect.withMessage("Selector %s meeting required SDK version", fmSelector)
+ .that(ConversionUtils.programSelectorMeetsSdkVersionRequirement(fmSelector,
+ Build.VERSION_CODES.TIRAMISU)).isTrue();
+ }
+
+ @Test
public void announcementFromHalAnnouncement_typesMatch() {
expect.withMessage("Announcement type")
.that(ANNOUNCEMENT.getType()).isEqualTo(TEST_ENABLED_TYPE);
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
index c5c6349df07e..201a50f49f88 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
@@ -330,10 +330,17 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
@Test
public void tune_withUnsupportedSelector_throwsException() throws Exception {
+ ProgramSelector.Identifier dabPrimaryId =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT,
+ /* value= */ 0xA000000111L);
+ ProgramSelector.Identifier[] dabSecondaryIds = new ProgramSelector.Identifier[]{
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE,
+ /* value= */ 1337),
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY,
+ /* value= */ 225648)};
+ ProgramSelector unsupportedSelector = new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB,
+ dabPrimaryId, dabSecondaryIds, /* vendorIds= */ null);
openAidlClients(/* numClients= */ 1);
- ProgramSelector unsupportedSelector = AidlTestUtils.makeProgramSelector(
- ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, new ProgramSelector.Identifier(
- ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, /* value= */ 300));
UnsupportedOperationException thrown = assertThrows(UnsupportedOperationException.class,
() -> mTunerSessions[0].tune(unsupportedSelector));
@@ -343,6 +350,21 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@Test
+ public void tune_withInvalidSelector_throwsIllegalArgumentException() throws Exception {
+ openAidlClients(/* numClients= */ 1);
+ ProgramSelector.Identifier invalidDabId = new ProgramSelector.Identifier(
+ ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, /* value= */ 0x1001);
+ ProgramSelector invalidSel = new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB,
+ invalidDabId, new ProgramSelector.Identifier[0], new long[0]);
+
+ IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
+ () -> mTunerSessions[0].tune(invalidSel));
+
+ assertWithMessage("Exception for tuning on DAB selector without DAB_SID_EXT primary id")
+ .that(thrown).hasMessageThat().contains("tune: INVALID_ARGUMENTS");
+ }
+
+ @Test
public void tune_forCurrentUser_doesNotTune() throws Exception {
openAidlClients(/* numClients= */ 1);
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
index db16c0362e7c..6e54dcf3d451 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
@@ -324,10 +324,17 @@ public final class TunerSessionHidlTest extends ExtendedRadioMockitoTestCase {
@Test
public void tune_withUnsupportedSelector_throwsException() throws Exception {
+ ProgramSelector.Identifier dabPrimaryId =
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT,
+ /* value= */ 0xA00111);
+ ProgramSelector.Identifier[] dabSecondaryIds = new ProgramSelector.Identifier[]{
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE,
+ /* value= */ 1337),
+ new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY,
+ /* value= */ 225648)};
+ ProgramSelector unsupportedSelector = new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB,
+ dabPrimaryId, dabSecondaryIds, /* vendorIds= */ null);
openAidlClients(/* numClients= */ 1);
- ProgramSelector unsupportedSelector = TestUtils.makeProgramSelector(
- ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, new ProgramSelector.Identifier(
- ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, /* value= */ 300));
UnsupportedOperationException thrown = assertThrows(UnsupportedOperationException.class,
() -> mTunerSessions[0].tune(unsupportedSelector));
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
index 3c0fda863cdc..d580d5ce8fa6 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
@@ -307,6 +307,9 @@ final class ConversionUtils {
static ProgramIdentifier identifierToHalProgramIdentifier(ProgramSelector.Identifier id) {
ProgramIdentifier hwId = new ProgramIdentifier();
hwId.type = id.getType();
+ if (hwId.type == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT) {
+ hwId.type = IdentifierType.DAB_SID_EXT;
+ }
hwId.value = id.getValue();
return hwId;
}
@@ -317,9 +320,49 @@ final class ConversionUtils {
if (id.type == IdentifierType.INVALID) {
return null;
}
- return new ProgramSelector.Identifier(id.type, id.value);
+ int idType;
+ if (id.type == IdentifierType.DAB_SID_EXT) {
+ idType = ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT;
+ } else {
+ idType = id.type;
+ }
+ return new ProgramSelector.Identifier(idType, id.value);
+ }
+
+ private static boolean isVendorIdentifierType(int idType) {
+ return idType >= IdentifierType.VENDOR_START && idType <= IdentifierType.VENDOR_END;
+ }
+
+ private static boolean isValidHalProgramSelector(
+ android.hardware.broadcastradio.ProgramSelector sel) {
+ if (sel.primaryId.type != IdentifierType.AMFM_FREQUENCY_KHZ
+ && sel.primaryId.type != IdentifierType.RDS_PI
+ && sel.primaryId.type != IdentifierType.HD_STATION_ID_EXT
+ && sel.primaryId.type != IdentifierType.DAB_SID_EXT
+ && sel.primaryId.type != IdentifierType.DRMO_SERVICE_ID
+ && sel.primaryId.type != IdentifierType.SXM_SERVICE_ID
+ && !isVendorIdentifierType(sel.primaryId.type)) {
+ return false;
+ }
+ if (sel.primaryId.type == IdentifierType.DAB_SID_EXT) {
+ boolean hasEnsemble = false;
+ boolean hasFrequency = false;
+ for (int i = 0; i < sel.secondaryIds.length; i++) {
+ if (sel.secondaryIds[i].type == IdentifierType.DAB_ENSEMBLE) {
+ hasEnsemble = true;
+ } else if (sel.secondaryIds[i].type == IdentifierType.DAB_FREQUENCY_KHZ) {
+ hasFrequency = true;
+ }
+ if (hasEnsemble && hasFrequency) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
}
+ @Nullable
static android.hardware.broadcastradio.ProgramSelector programSelectorToHalProgramSelector(
ProgramSelector sel) {
android.hardware.broadcastradio.ProgramSelector hwSel =
@@ -332,6 +375,9 @@ final class ConversionUtils {
secondaryIdList.add(identifierToHalProgramIdentifier(secondaryIds[i]));
}
hwSel.secondaryIds = secondaryIdList.toArray(ProgramIdentifier[]::new);
+ if (!isValidHalProgramSelector(hwSel)) {
+ return null;
+ }
return hwSel;
}
@@ -344,7 +390,7 @@ final class ConversionUtils {
@Nullable
static ProgramSelector programSelectorFromHalProgramSelector(
android.hardware.broadcastradio.ProgramSelector sel) {
- if (isEmpty(sel)) {
+ if (isEmpty(sel) || !isValidHalProgramSelector(sel)) {
return null;
}
@@ -432,7 +478,34 @@ final class ConversionUtils {
return builder.build();
}
+ private static boolean isValidLogicallyTunedTo(ProgramIdentifier id) {
+ return id.type == IdentifierType.AMFM_FREQUENCY_KHZ || id.type == IdentifierType.RDS_PI
+ || id.type == IdentifierType.HD_STATION_ID_EXT
+ || id.type == IdentifierType.DAB_SID_EXT
+ || id.type == IdentifierType.DRMO_SERVICE_ID
+ || id.type == IdentifierType.SXM_SERVICE_ID
+ || isVendorIdentifierType(id.type);
+ }
+
+ private static boolean isValidPhysicallyTunedTo(ProgramIdentifier id) {
+ return id.type == IdentifierType.AMFM_FREQUENCY_KHZ
+ || id.type == IdentifierType.DAB_FREQUENCY_KHZ
+ || id.type == IdentifierType.DRMO_FREQUENCY_KHZ
+ || id.type == IdentifierType.SXM_CHANNEL
+ || isVendorIdentifierType(id.type);
+ }
+
+ private static boolean isValidHalProgramInfo(ProgramInfo info) {
+ return isValidHalProgramSelector(info.selector)
+ && isValidLogicallyTunedTo(info.logicallyTunedTo)
+ && isValidPhysicallyTunedTo(info.physicallyTunedTo);
+ }
+
+ @Nullable
static RadioManager.ProgramInfo programInfoFromHalProgramInfo(ProgramInfo info) {
+ if (!isValidHalProgramInfo(info)) {
+ return null;
+ }
Collection<ProgramSelector.Identifier> relatedContent = new ArrayList<>();
if (info.relatedContent != null) {
for (int i = 0; i < info.relatedContent.length; i++) {
@@ -485,7 +558,14 @@ final class ConversionUtils {
static ProgramList.Chunk chunkFromHalProgramListChunk(ProgramListChunk chunk) {
Set<RadioManager.ProgramInfo> modified = new ArraySet<>(chunk.modified.length);
for (int i = 0; i < chunk.modified.length; i++) {
- modified.add(programInfoFromHalProgramInfo(chunk.modified[i]));
+ RadioManager.ProgramInfo modifiedInfo =
+ programInfoFromHalProgramInfo(chunk.modified[i]);
+ if (modifiedInfo == null) {
+ Slogf.w(TAG, "Program info %s in program list chunk is not valid",
+ chunk.modified[i]);
+ continue;
+ }
+ modified.add(modifiedInfo);
}
Set<ProgramSelector.Identifier> removed = new ArraySet<>();
if (chunk.removed != null) {
@@ -558,7 +638,7 @@ final class ConversionUtils {
Announcement hwAnnouncement) {
return new android.hardware.radio.Announcement(
Objects.requireNonNull(programSelectorFromHalProgramSelector(
- hwAnnouncement.selector)),
+ hwAnnouncement.selector), "Program selector can not be null"),
hwAnnouncement.type,
vendorInfoFromHalVendorKeyValues(hwAnnouncement.vendorInfo)
);
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java b/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java
index 095a5fa1cf30..39b13547cf93 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java
@@ -24,6 +24,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.utils.Slogf;
import java.util.ArrayList;
import java.util.Collection;
@@ -37,6 +38,7 @@ import java.util.Set;
*/
final class ProgramInfoCache {
+ private static final String TAG = "BcRadioAidlSrv.cache";
/**
* Maximum number of {@link RadioManager#ProgramInfo} elements that will be put into a
* ProgramList.Chunk.mModified array. Used to try to ensure a single ProgramList.Chunk
@@ -124,6 +126,10 @@ final class ProgramInfoCache {
for (int i = 0; i < chunk.modified.length; i++) {
RadioManager.ProgramInfo programInfo =
ConversionUtils.programInfoFromHalProgramInfo(chunk.modified[i]);
+ if (programInfo == null) {
+ Slogf.e(TAG, "Program info in program info %s in chunk is not valid",
+ chunk.modified[i]);
+ }
mProgramInfoMap.put(programInfo.getSelector().getPrimaryId(), programInfo);
}
if (chunk.removed != null) {
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
index 6193f234730d..f8c19ae2b8f1 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
@@ -97,10 +97,10 @@ final class RadioModule {
public void onTuneFailed(int result, ProgramSelector programSelector) {
fireLater(() -> {
+ android.hardware.radio.ProgramSelector csel =
+ ConversionUtils.programSelectorFromHalProgramSelector(programSelector);
+ int tunerResult = ConversionUtils.halResultToTunerResult(result);
synchronized (mLock) {
- android.hardware.radio.ProgramSelector csel =
- ConversionUtils.programSelectorFromHalProgramSelector(programSelector);
- int tunerResult = ConversionUtils.halResultToTunerResult(result);
fanoutAidlCallbackLocked((cb, sdkVersion) -> {
if (csel != null && !ConversionUtils
.programSelectorMeetsSdkVersionRequirement(csel, sdkVersion)) {
@@ -117,10 +117,12 @@ final class RadioModule {
@Override
public void onCurrentProgramInfoChanged(ProgramInfo halProgramInfo) {
fireLater(() -> {
+ RadioManager.ProgramInfo currentProgramInfo =
+ ConversionUtils.programInfoFromHalProgramInfo(halProgramInfo);
+ Objects.requireNonNull(currentProgramInfo,
+ "Program info from AIDL HAL is invalid");
synchronized (mLock) {
- mCurrentProgramInfo =
- ConversionUtils.programInfoFromHalProgramInfo(halProgramInfo);
- RadioManager.ProgramInfo currentProgramInfo = mCurrentProgramInfo;
+ mCurrentProgramInfo = currentProgramInfo;
fanoutAidlCallbackLocked((cb, sdkVersion) -> {
if (!ConversionUtils.programInfoMeetsSdkVersionRequirement(
currentProgramInfo, sdkVersion)) {
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
index d700ed01b3c3..fe8c23845d2a 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
@@ -203,10 +203,15 @@ final class TunerSession extends ITuner.Stub {
Slogf.w(TAG, "Cannot tune on AIDL HAL client from non-current user");
return;
}
+ android.hardware.broadcastradio.ProgramSelector hwSel =
+ ConversionUtils.programSelectorToHalProgramSelector(selector);
+ if (hwSel == null) {
+ throw new IllegalArgumentException("tune: INVALID_ARGUMENTS for program selector");
+ }
synchronized (mLock) {
checkNotClosedLocked();
try {
- mService.tune(ConversionUtils.programSelectorToHalProgramSelector(selector));
+ mService.tune(hwSel);
} catch (RuntimeException ex) {
throw ConversionUtils.throwOnError(ex, /* action= */ "tune");
}