diff options
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"); } |