Merge changes from topic "radio-dab-u"
* changes: Add exception and conversion tests for AIDL client Add unit tests about throwing expection for radio Improve DAB support in radio service and manager
This commit is contained in:
@@ -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).
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
@@ -275,6 +275,19 @@ public final class ProgramListTest {
|
||||
assertWithMessage("Chunks").that(chunks).hasLength(CREATOR_ARRAY_SIZE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProgramList_forTunerAdapterWhenServiceDied_fails() throws Exception {
|
||||
Map<String, String> parameters = Map.of("ParameterKeyMock", "ParameterValueMock");
|
||||
createRadioTuner();
|
||||
doThrow(new RemoteException()).when(mTunerMock).startProgramListUpdates(any());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.getProgramList(parameters));
|
||||
|
||||
assertWithMessage("Exception for getting program list when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDynamicProgramList_forTunerAdapter() throws Exception {
|
||||
createRadioTuner();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ package android.hardware.radio.tests.unittests;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -105,17 +107,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 +861,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
|
||||
@@ -1005,6 +1007,35 @@ public final class RadioManagerTest {
|
||||
.that(modules).containsExactly(AMFM_PROPERTIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listModules_forRadioManagerWithNullListAsInput_fails() throws Exception {
|
||||
createRadioManager();
|
||||
|
||||
assertWithMessage("Status when listing module with empty list input")
|
||||
.that(mRadioManager.listModules(null)).isEqualTo(RadioManager.STATUS_BAD_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listModules_withNullListFromService_fails() throws Exception {
|
||||
createRadioManager();
|
||||
when(mRadioServiceMock.listModules()).thenReturn(null);
|
||||
List<RadioManager.ModuleProperties> modules = new ArrayList<>();
|
||||
|
||||
assertWithMessage("Status for listing module when getting null list from HAL client")
|
||||
.that(mRadioManager.listModules(modules)).isEqualTo(RadioManager.STATUS_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listModules_whenServiceDied_fails() throws Exception {
|
||||
createRadioManager();
|
||||
when(mRadioServiceMock.listModules()).thenThrow(new RemoteException());
|
||||
List<RadioManager.ModuleProperties> modules = new ArrayList<>();
|
||||
|
||||
assertWithMessage("Status for listing module when HAL client service is dead")
|
||||
.that(mRadioManager.listModules(modules))
|
||||
.isEqualTo(RadioManager.STATUS_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openTuner_forRadioModule() throws Exception {
|
||||
createRadioManager();
|
||||
@@ -1018,6 +1049,18 @@ public final class RadioManagerTest {
|
||||
anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openTuner_whenServiceDied_returnsNull() throws Exception {
|
||||
createRadioManager();
|
||||
when(mRadioServiceMock.openTuner(anyInt(), any(), anyBoolean(), any(), anyInt()))
|
||||
.thenThrow(new RemoteException());
|
||||
|
||||
RadioTuner nullTuner = mRadioManager.openTuner(/* moduleId= */ 0, FM_BAND_CONFIG,
|
||||
/* withAudio= */ true, mCallbackMock, /* handler= */ null);
|
||||
|
||||
assertWithMessage("Radio tuner when service is dead").that(nullTuner).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addAnnouncementListener_withListenerNotAddedBefore() throws Exception {
|
||||
createRadioManager();
|
||||
@@ -1048,6 +1091,21 @@ public final class RadioManagerTest {
|
||||
verify(mCloseHandleMock).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addAnnouncementListener_whenServiceDied_throwException() throws Exception {
|
||||
createRadioManager();
|
||||
String exceptionMessage = "service is dead";
|
||||
when(mRadioServiceMock.addAnnouncementListener(any(), any()))
|
||||
.thenThrow(new RemoteException(exceptionMessage));
|
||||
Set<Integer> enableTypeSet = createAnnouncementTypeSet(EVENT_ANNOUNCEMENT_TYPE);
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioManager.addAnnouncementListener(enableTypeSet, mEventListener));
|
||||
|
||||
assertWithMessage("Exception for adding announcement listener with dead service")
|
||||
.that(thrown).hasMessageThat().contains(exceptionMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeAnnouncementListener_withListenerNotAddedBefore_ignores() throws Exception {
|
||||
createRadioManager();
|
||||
@@ -1104,8 +1162,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,13 @@ package android.hardware.radio.tests.unittests;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -37,6 +40,7 @@ import android.hardware.radio.RadioManager;
|
||||
import android.hardware.radio.RadioMetadata;
|
||||
import android.hardware.radio.RadioTuner;
|
||||
import android.os.Build;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -46,7 +50,6 @@ import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -130,6 +133,24 @@ public final class TunerAdapterTest {
|
||||
.that(status).isEqualTo(RadioManager.STATUS_OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConfiguration_withInvalidParameters_fails() throws Exception {
|
||||
doThrow(new IllegalArgumentException()).when(mTunerMock).setConfiguration(any());
|
||||
|
||||
assertWithMessage("Status for setting configuration with invalid parameters")
|
||||
.that(mRadioTuner.setConfiguration(TEST_BAND_CONFIG))
|
||||
.isEqualTo(RadioManager.STATUS_BAD_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConfiguration_whenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).setConfiguration(any());
|
||||
|
||||
assertWithMessage("Status for setting configuration when service is dead")
|
||||
.that(mRadioTuner.setConfiguration(TEST_BAND_CONFIG))
|
||||
.isEqualTo(RadioManager.STATUS_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConfiguration_forTunerAdapter() throws Exception {
|
||||
when(mTunerMock.getConfiguration()).thenReturn(TEST_BAND_CONFIG);
|
||||
@@ -143,14 +164,52 @@ public final class TunerAdapterTest {
|
||||
.that(bandConfigs[0]).isEqualTo(TEST_BAND_CONFIG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConfiguration_withInvalidParameters_fails() throws Exception {
|
||||
RadioManager.BandConfig[] bandConfigs = new RadioManager.BandConfig[0];
|
||||
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
|
||||
() -> mRadioTuner.getConfiguration(bandConfigs));
|
||||
|
||||
assertWithMessage("Exception for getting configuration with invalid parameters")
|
||||
.that(thrown).hasMessageThat().contains("must be an array of length 1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConfiguration_whenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).getConfiguration();
|
||||
RadioManager.BandConfig[] bandConfigs = new RadioManager.BandConfig[1];
|
||||
|
||||
assertWithMessage("Status for getting configuration when service is dead")
|
||||
.that(mRadioTuner.getConfiguration(bandConfigs))
|
||||
.isEqualTo(RadioManager.STATUS_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMute_forTunerAdapter() {
|
||||
int status = mRadioTuner.setMute(/* mute= */ true);
|
||||
int status = mRadioTuner.setMute(true);
|
||||
|
||||
assertWithMessage("Status for setting mute")
|
||||
.that(status).isEqualTo(RadioManager.STATUS_OK);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMute_whenIllegalState_fails() throws Exception {
|
||||
doThrow(new IllegalStateException()).when(mTunerMock).setMuted(anyBoolean());
|
||||
|
||||
assertWithMessage("Status for setting muted when service is in illegal state")
|
||||
.that(mRadioTuner.setMute(true)).isEqualTo(RadioManager.STATUS_ERROR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setMute_whenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).setMuted(anyBoolean());
|
||||
|
||||
assertWithMessage("Status for setting muted when service is dead")
|
||||
.that(mRadioTuner.setMute(true))
|
||||
.isEqualTo(RadioManager.STATUS_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMute_forTunerAdapter() throws Exception {
|
||||
when(mTunerMock.isMuted()).thenReturn(true);
|
||||
@@ -160,6 +219,14 @@ public final class TunerAdapterTest {
|
||||
assertWithMessage("Mute status").that(muteStatus).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMute_whenServiceDied_returnsTrue() throws Exception {
|
||||
when(mTunerMock.isMuted()).thenThrow(new RemoteException());
|
||||
|
||||
assertWithMessage("Status for getting muted when service is dead")
|
||||
.that(mRadioTuner.getMute()).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void step_forTunerAdapter_succeeds() throws Exception {
|
||||
doAnswer(invocation -> {
|
||||
@@ -175,6 +242,24 @@ public final class TunerAdapterTest {
|
||||
verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onProgramInfoChanged(FM_PROGRAM_INFO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void step_whenIllegalState_fails() throws Exception {
|
||||
doThrow(new IllegalStateException()).when(mTunerMock).step(anyBoolean(), anyBoolean());
|
||||
|
||||
assertWithMessage("Status for stepping when service is in illegal state")
|
||||
.that(mRadioTuner.step(RadioTuner.DIRECTION_UP, /* skipSubChannel= */ false))
|
||||
.isEqualTo(RadioManager.STATUS_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void step_whenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).step(anyBoolean(), anyBoolean());
|
||||
|
||||
assertWithMessage("Status for stepping when service is dead")
|
||||
.that(mRadioTuner.step(RadioTuner.DIRECTION_UP, /* skipSubChannel= */ false))
|
||||
.isEqualTo(RadioManager.STATUS_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scan_forTunerAdapter_succeeds() throws Exception {
|
||||
doAnswer(invocation -> {
|
||||
@@ -190,6 +275,24 @@ public final class TunerAdapterTest {
|
||||
verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onProgramInfoChanged(FM_PROGRAM_INFO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scan_whenIllegalState_fails() throws Exception {
|
||||
doThrow(new IllegalStateException()).when(mTunerMock).seek(anyBoolean(), anyBoolean());
|
||||
|
||||
assertWithMessage("Status for scanning when service is in illegal state")
|
||||
.that(mRadioTuner.scan(RadioTuner.DIRECTION_UP, /* skipSubChannel= */ false))
|
||||
.isEqualTo(RadioManager.STATUS_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scan_whenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).seek(anyBoolean(), anyBoolean());
|
||||
|
||||
assertWithMessage("Status for scan when service is dead")
|
||||
.that(mRadioTuner.scan(RadioTuner.DIRECTION_UP, /* skipSubChannel= */ true))
|
||||
.isEqualTo(RadioManager.STATUS_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seek_forTunerAdapter_succeeds() throws Exception {
|
||||
doAnswer(invocation -> {
|
||||
@@ -197,7 +300,7 @@ public final class TunerAdapterTest {
|
||||
return RadioManager.STATUS_OK;
|
||||
}).when(mTunerMock).seek(anyBoolean(), anyBoolean());
|
||||
|
||||
int scanStatus = mRadioTuner.scan(RadioTuner.DIRECTION_DOWN, /* skipSubChannel= */ false);
|
||||
int scanStatus = mRadioTuner.seek(RadioTuner.DIRECTION_DOWN, /* skipSubChannel= */ false);
|
||||
|
||||
verify(mTunerMock).seek(/* directionDown= */ true, /* skipSubChannel= */ false);
|
||||
assertWithMessage("Status for seeking")
|
||||
@@ -212,12 +315,30 @@ public final class TunerAdapterTest {
|
||||
return RadioManager.STATUS_OK;
|
||||
}).when(mTunerMock).seek(anyBoolean(), anyBoolean());
|
||||
|
||||
mRadioTuner.scan(RadioTuner.DIRECTION_UP, /* skipSubChannel*/ true);
|
||||
mRadioTuner.seek(RadioTuner.DIRECTION_UP, /* skipSubChannel= */ true);
|
||||
|
||||
verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onTuneFailed(
|
||||
RadioTuner.TUNER_RESULT_TIMEOUT, FM_SELECTOR);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seek_whenIllegalState_fails() throws Exception {
|
||||
doThrow(new IllegalStateException()).when(mTunerMock).seek(anyBoolean(), anyBoolean());
|
||||
|
||||
assertWithMessage("Status for seeking when service is in illegal state")
|
||||
.that(mRadioTuner.seek(RadioTuner.DIRECTION_UP, /* skipSubChannel= */ false))
|
||||
.isEqualTo(RadioManager.STATUS_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seek_whenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).seek(anyBoolean(), anyBoolean());
|
||||
|
||||
assertWithMessage("Status for seeking when service is dead")
|
||||
.that(mRadioTuner.seek(RadioTuner.DIRECTION_UP, /* skipSubChannel= */ true))
|
||||
.isEqualTo(RadioManager.STATUS_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tune_withChannelsForTunerAdapter_succeeds() {
|
||||
int status = mRadioTuner.tune(/* channel= */ 92300, /* subChannel= */ 0);
|
||||
@@ -227,6 +348,33 @@ public final class TunerAdapterTest {
|
||||
verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onProgramInfoChanged(FM_PROGRAM_INFO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tune_withInvalidChannel_fails() throws Exception {
|
||||
doThrow(new IllegalArgumentException()).when(mTunerMock).tune(any());
|
||||
|
||||
assertWithMessage("Status for tuning when service is in illegal state")
|
||||
.that(mRadioTuner.tune(/* channel= */ 300, /* subChannel= */ 0))
|
||||
.isEqualTo(RadioManager.STATUS_BAD_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tune_withChannelsWhenIllegalState_fails() throws Exception {
|
||||
doThrow(new IllegalStateException()).when(mTunerMock).tune(any());
|
||||
|
||||
assertWithMessage("Status for tuning when service is in illegal state")
|
||||
.that(mRadioTuner.tune(/* channel= */ 92300, /* subChannel= */ 0))
|
||||
.isEqualTo(RadioManager.STATUS_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tune_withChannelsWhenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).tune(any());
|
||||
|
||||
assertWithMessage("Status for tuning when service is dead")
|
||||
.that(mRadioTuner.tune(/* channel= */ 92300, /* subChannel= */ 0))
|
||||
.isEqualTo(RadioManager.STATUS_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tune_withValidSelectorForTunerAdapter_succeeds() throws Exception {
|
||||
mRadioTuner.tune(FM_SELECTOR);
|
||||
@@ -249,6 +397,17 @@ public final class TunerAdapterTest {
|
||||
.onTuneFailed(RadioTuner.TUNER_RESULT_INVALID_ARGUMENTS, invalidSelector);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tune_withSelectorWhenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).tune(any());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.tune(FM_SELECTOR));
|
||||
|
||||
assertWithMessage("Exception for tuning when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancel_forTunerAdapter() throws Exception {
|
||||
mRadioTuner.tune(FM_SELECTOR);
|
||||
@@ -258,6 +417,22 @@ public final class TunerAdapterTest {
|
||||
verify(mTunerMock).cancel();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancel_whenIllegalState_fails() throws Exception {
|
||||
doThrow(new IllegalStateException()).when(mTunerMock).cancel();
|
||||
|
||||
assertWithMessage("Status for canceling when service is in illegal state")
|
||||
.that(mRadioTuner.cancel()).isEqualTo(RadioManager.STATUS_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancel_forTunerAdapterWhenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).cancel();
|
||||
|
||||
assertWithMessage("Status for canceling when service is dead")
|
||||
.that(mRadioTuner.cancel()).isEqualTo(RadioManager.STATUS_DEAD_OBJECT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancelAnnouncement_forTunerAdapter() throws Exception {
|
||||
mRadioTuner.cancelAnnouncement();
|
||||
@@ -265,6 +440,17 @@ public final class TunerAdapterTest {
|
||||
verify(mTunerMock).cancelAnnouncement();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancelAnnouncement_whenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).cancelAnnouncement();
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.cancelAnnouncement());
|
||||
|
||||
assertWithMessage("Exception for canceling announcement when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProgramInfo_beforeProgramInfoSetForTunerAdapter() {
|
||||
RadioManager.ProgramInfo[] programInfoArray = new RadioManager.ProgramInfo[1];
|
||||
@@ -295,12 +481,23 @@ public final class TunerAdapterTest {
|
||||
when(mTunerMock.getImage(anyInt())).thenReturn(bitmapExpected);
|
||||
int imageId = 1;
|
||||
|
||||
Bitmap image = mRadioTuner.getMetadataImage(/* id= */ imageId);
|
||||
Bitmap image = mRadioTuner.getMetadataImage(imageId);
|
||||
|
||||
assertWithMessage("Image obtained from id %s", imageId)
|
||||
.that(image).isEqualTo(bitmapExpected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMetadataImage_whenServiceDied_fails() throws Exception {
|
||||
when(mTunerMock.getImage(anyInt())).thenThrow(new RemoteException());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.getMetadataImage(/* id= */ 1));
|
||||
|
||||
assertWithMessage("Exception for getting metadata image when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startBackgroundScan_forTunerAdapter() throws Exception {
|
||||
when(mTunerMock.startBackgroundScan()).thenReturn(false);
|
||||
@@ -311,6 +508,17 @@ public final class TunerAdapterTest {
|
||||
assertWithMessage("Status for starting background scan").that(scanStatus).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startBackgroundScan_whenServiceDied_fails() throws Exception {
|
||||
when(mTunerMock.startBackgroundScan()).thenThrow(new RemoteException());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.startBackgroundScan());
|
||||
|
||||
assertWithMessage("Exception for background scan when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAnalogForced_forTunerAdapter() throws Exception {
|
||||
when(mTunerMock.isConfigFlagSet(RadioManager.CONFIG_FORCE_ANALOG)).thenReturn(true);
|
||||
@@ -321,6 +529,19 @@ public final class TunerAdapterTest {
|
||||
.that(isAnalogForced).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAnalogForced_whenNotSupported_fails() throws Exception {
|
||||
String errorMessage = "Analog forced switch is not supported";
|
||||
when(mTunerMock.isConfigFlagSet(RadioManager.CONFIG_FORCE_ANALOG))
|
||||
.thenThrow(new UnsupportedOperationException(errorMessage));
|
||||
|
||||
IllegalStateException thrown = assertThrows(IllegalStateException.class,
|
||||
() -> mRadioTuner.isAnalogForced());
|
||||
|
||||
assertWithMessage("Exception for checking analog playback switch when not supported")
|
||||
.that(thrown).hasMessageThat().contains(errorMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAnalogForced_forTunerAdapter() throws Exception {
|
||||
boolean analogForced = true;
|
||||
@@ -330,6 +551,19 @@ public final class TunerAdapterTest {
|
||||
verify(mTunerMock).setConfigFlag(RadioManager.CONFIG_FORCE_ANALOG, analogForced);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAnalogForced_whenNotSupported_fails() throws Exception {
|
||||
String errorMessage = "Analog forced switch is not supported";
|
||||
doThrow(new UnsupportedOperationException(errorMessage))
|
||||
.when(mTunerMock).setConfigFlag(eq(RadioManager.CONFIG_FORCE_ANALOG), anyBoolean());
|
||||
|
||||
IllegalStateException thrown = assertThrows(IllegalStateException.class,
|
||||
() -> mRadioTuner.setAnalogForced(/* isForced= */ false));
|
||||
|
||||
assertWithMessage("Exception for setting analog playback switch when not supported")
|
||||
.that(thrown).hasMessageThat().contains(errorMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSupported_forTunerAdapter() throws Exception {
|
||||
when(mTunerMock.isConfigFlagSupported(RadioManager.CONFIG_DAB_DAB_LINKING))
|
||||
@@ -342,6 +576,17 @@ public final class TunerAdapterTest {
|
||||
.that(dabFmSoftLinking).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSupported_whenServiceDied_fails() throws Exception {
|
||||
when(mTunerMock.isConfigFlagSupported(anyInt())).thenThrow(new RemoteException());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.isConfigFlagSupported(RadioManager.CONFIG_DAB_DAB_LINKING));
|
||||
|
||||
assertWithMessage("Exception for checking config flag support when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSet_forTunerAdapter() throws Exception {
|
||||
when(mTunerMock.isConfigFlagSet(RadioManager.CONFIG_DAB_FM_SOFT_LINKING))
|
||||
@@ -354,6 +599,17 @@ public final class TunerAdapterTest {
|
||||
.that(dabFmSoftLinking).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSet_whenServiceDied_fails() throws Exception {
|
||||
when(mTunerMock.isConfigFlagSet(anyInt())).thenThrow(new RemoteException());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.isConfigFlagSet(RadioManager.CONFIG_DAB_DAB_LINKING));
|
||||
|
||||
assertWithMessage("Exception for getting config flag when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConfigFlag_forTunerAdapter() throws Exception {
|
||||
boolean dabFmLinking = true;
|
||||
@@ -363,9 +619,21 @@ public final class TunerAdapterTest {
|
||||
verify(mTunerMock).setConfigFlag(RadioManager.CONFIG_DAB_FM_LINKING, dabFmLinking);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConfigFlag_whenServiceDied_fails() throws Exception {
|
||||
doThrow(new RemoteException()).when(mTunerMock).setConfigFlag(anyInt(), anyBoolean());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.setConfigFlag(RadioManager.CONFIG_DAB_DAB_LINKING,
|
||||
/* value= */ true));
|
||||
|
||||
assertWithMessage("Exception for setting config flag when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getParameters_forTunerAdapter() throws Exception {
|
||||
List<String> parameterKeys = Arrays.asList("ParameterKeyMock");
|
||||
List<String> parameterKeys = List.of("ParameterKeyMock");
|
||||
Map<String, String> parameters = Map.of("ParameterKeyMock", "ParameterValueMock");
|
||||
when(mTunerMock.getParameters(parameterKeys)).thenReturn(parameters);
|
||||
|
||||
@@ -373,6 +641,18 @@ public final class TunerAdapterTest {
|
||||
.that(mRadioTuner.getParameters(parameterKeys)).isEqualTo(parameters);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getParameters_whenServiceDied_fails() throws Exception {
|
||||
List<String> parameterKeys = List.of("ParameterKeyMock");
|
||||
when(mTunerMock.getParameters(parameterKeys)).thenThrow(new RemoteException());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.getParameters(parameterKeys));
|
||||
|
||||
assertWithMessage("Exception for getting parameters when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setParameters_forTunerAdapter() throws Exception {
|
||||
Map<String, String> parameters = Map.of("ParameterKeyMock", "ParameterValueMock");
|
||||
@@ -382,6 +662,18 @@ public final class TunerAdapterTest {
|
||||
.that(mRadioTuner.setParameters(parameters)).isEqualTo(parameters);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setParameters_whenServiceDied_fails() throws Exception {
|
||||
Map<String, String> parameters = Map.of("ParameterKeyMock", "ParameterValueMock");
|
||||
when(mTunerMock.setParameters(parameters)).thenThrow(new RemoteException());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class,
|
||||
() -> mRadioTuner.setParameters(parameters));
|
||||
|
||||
assertWithMessage("Exception for setting parameters when service is dead")
|
||||
.that(thrown).hasMessageThat().contains("Service died");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAntennaConnected_forTunerAdapter() throws Exception {
|
||||
mTunerCallback.onAntennaState(/* connected= */ false);
|
||||
@@ -390,6 +682,15 @@ public final class TunerAdapterTest {
|
||||
.that(mRadioTuner.isAntennaConnected()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onError_forTunerAdapter() throws Exception {
|
||||
int errorStatus = RadioTuner.ERROR_HARDWARE_FAILURE;
|
||||
|
||||
mTunerCallback.onError(errorStatus);
|
||||
|
||||
verify(mCallbackMock, timeout(CALLBACK_TIMEOUT_MS)).onError(errorStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasControl_forTunerAdapter() throws Exception {
|
||||
when(mTunerMock.isClosed()).thenReturn(true);
|
||||
@@ -397,6 +698,14 @@ public final class TunerAdapterTest {
|
||||
assertWithMessage("Control on tuner").that(mRadioTuner.hasControl()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasControl_whenServiceDied_returnsFalse() throws Exception {
|
||||
when(mTunerMock.isClosed()).thenThrow(new RemoteException());
|
||||
|
||||
assertWithMessage("Control on tuner when service is dead")
|
||||
.that(mRadioTuner.hasControl()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onConfigurationChanged_forTunerCallbackAdapter() throws Exception {
|
||||
mTunerCallback.onConfigurationChanged(TEST_BAND_CONFIG);
|
||||
|
||||
@@ -19,6 +19,7 @@ import android.hardware.broadcastradio.IdentifierType;
|
||||
import android.hardware.broadcastradio.Metadata;
|
||||
import android.hardware.broadcastradio.ProgramIdentifier;
|
||||
import android.hardware.broadcastradio.ProgramInfo;
|
||||
import android.hardware.broadcastradio.ProgramListChunk;
|
||||
import android.hardware.broadcastradio.VendorKeyValue;
|
||||
import android.hardware.radio.ProgramSelector;
|
||||
import android.hardware.radio.RadioManager;
|
||||
@@ -41,17 +42,25 @@ final class AidlTestUtils {
|
||||
/* dabFrequencyTable= */ null, /* vendorInfo= */ null);
|
||||
}
|
||||
|
||||
static RadioManager.ProgramInfo makeProgramInfo(ProgramSelector selector, int signalQuality) {
|
||||
static RadioManager.ProgramInfo makeProgramInfo(ProgramSelector selector,
|
||||
ProgramSelector.Identifier logicallyTunedTo,
|
||||
ProgramSelector.Identifier physicallyTunedTo, int signalQuality) {
|
||||
return new RadioManager.ProgramInfo(selector,
|
||||
selector.getPrimaryId(), selector.getPrimaryId(), /* relatedContents= */ null,
|
||||
logicallyTunedTo, physicallyTunedTo, /* relatedContents= */ null,
|
||||
/* infoFlags= */ 0, signalQuality,
|
||||
new RadioMetadata.Builder().build(), new ArrayMap<>());
|
||||
}
|
||||
|
||||
static RadioManager.ProgramInfo makeProgramInfo(int programType,
|
||||
ProgramSelector.Identifier identifier, int signalQuality) {
|
||||
ProgramSelector selector = makeProgramSelector(programType, identifier);
|
||||
return makeProgramInfo(selector, signalQuality);
|
||||
static RadioManager.ProgramInfo makeProgramInfo(ProgramSelector selector, int signalQuality) {
|
||||
return makeProgramInfo(selector, selector.getPrimaryId(), selector.getPrimaryId(),
|
||||
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) {
|
||||
@@ -67,44 +76,48 @@ final class AidlTestUtils {
|
||||
}
|
||||
|
||||
static android.hardware.broadcastradio.ProgramSelector makeHalFmSelector(int freq) {
|
||||
ProgramIdentifier halId = new ProgramIdentifier();
|
||||
halId.type = IdentifierType.AMFM_FREQUENCY_KHZ;
|
||||
halId.value = freq;
|
||||
|
||||
android.hardware.broadcastradio.ProgramSelector halSelector =
|
||||
new android.hardware.broadcastradio.ProgramSelector();
|
||||
halSelector.primaryId = halId;
|
||||
halSelector.secondaryIds = new ProgramIdentifier[0];
|
||||
return halSelector;
|
||||
ProgramIdentifier halId = makeHalIdentifier(IdentifierType.AMFM_FREQUENCY_KHZ, freq);
|
||||
return makeHalSelector(halId, /* secondaryIds= */ new ProgramIdentifier[0]);
|
||||
}
|
||||
|
||||
static ProgramInfo programInfoToHalProgramInfo(RadioManager.ProgramInfo info) {
|
||||
// Note that because ConversionUtils does not by design provide functions for all
|
||||
// conversions, this function only copies fields that are set by makeProgramInfo().
|
||||
ProgramInfo hwInfo = new ProgramInfo();
|
||||
hwInfo.selector = ConversionUtils.programSelectorToHalProgramSelector(info.getSelector());
|
||||
hwInfo.logicallyTunedTo =
|
||||
ConversionUtils.identifierToHalProgramIdentifier(info.getLogicallyTunedTo());
|
||||
hwInfo.physicallyTunedTo =
|
||||
ConversionUtils.identifierToHalProgramIdentifier(info.getPhysicallyTunedTo());
|
||||
hwInfo.signalQuality = info.getSignalStrength();
|
||||
hwInfo.relatedContent = new ProgramIdentifier[]{};
|
||||
hwInfo.metadata = new Metadata[]{};
|
||||
return hwInfo;
|
||||
static android.hardware.broadcastradio.ProgramSelector makeHalSelector(
|
||||
ProgramIdentifier primaryId, ProgramIdentifier[] secondaryIds) {
|
||||
android.hardware.broadcastradio.ProgramSelector hwSelector =
|
||||
new android.hardware.broadcastradio.ProgramSelector();
|
||||
hwSelector.primaryId = primaryId;
|
||||
hwSelector.secondaryIds = secondaryIds;
|
||||
return hwSelector;
|
||||
}
|
||||
|
||||
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[]{};
|
||||
return hwInfo;
|
||||
}
|
||||
|
||||
static ProgramListChunk makeProgramListChunk(boolean purge, boolean complete,
|
||||
ProgramInfo[] modified, ProgramIdentifier[] removed) {
|
||||
ProgramListChunk halChunk = new ProgramListChunk();
|
||||
halChunk.purge = purge;
|
||||
halChunk.complete = complete;
|
||||
halChunk.modified = modified;
|
||||
halChunk.removed = removed;
|
||||
return halChunk;
|
||||
}
|
||||
|
||||
static VendorKeyValue makeVendorKeyValue(String vendorKey, String vendorValue) {
|
||||
VendorKeyValue vendorKeyValue = new VendorKeyValue();
|
||||
vendorKeyValue.key = vendorKey;
|
||||
|
||||
@@ -172,6 +172,19 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
|
||||
.that(thrown).hasMessageThat().contains("Cannot open session for non-current user");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openSession_withoutAudio_fails() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
|
||||
() -> mBroadcastRadioService.openSession(FM_RADIO_MODULE_ID,
|
||||
/* legacyConfig= */ null, /* withAudio= */ false, mTunerCallbackMock,
|
||||
TARGET_SDK_VERSION));
|
||||
|
||||
assertWithMessage("Exception for opening session without audio")
|
||||
.that(thrown).hasMessageThat().contains("not supported");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void binderDied_forDeathRecipient() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
|
||||
@@ -20,9 +20,13 @@ 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.ProgramListChunk;
|
||||
import android.hardware.broadcastradio.Properties;
|
||||
import android.hardware.broadcastradio.VendorKeyValue;
|
||||
import android.hardware.radio.Announcement;
|
||||
import android.hardware.radio.ProgramList;
|
||||
import android.hardware.radio.ProgramSelector;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.os.Build;
|
||||
@@ -33,19 +37,20 @@ import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class ConversionUtilsTest {
|
||||
|
||||
private static final int FM_LOWER_LIMIT = 87500;
|
||||
private static final int FM_UPPER_LIMIT = 108000;
|
||||
private static final int FM_LOWER_LIMIT = 87_500;
|
||||
private static final int FM_UPPER_LIMIT = 108_000;
|
||||
private static final int FM_SPACING = 200;
|
||||
private static final int AM_LOWER_LIMIT = 540;
|
||||
private static final int AM_UPPER_LIMIT = 1700;
|
||||
private static final int AM_UPPER_LIMIT = 1_700;
|
||||
private static final int AM_SPACING = 10;
|
||||
private static final String DAB_ENTRY_LABEL_1 = "5A";
|
||||
private static final int DAB_ENTRY_FREQUENCY_1 = 174928;
|
||||
private static final int DAB_ENTRY_FREQUENCY_1 = 174_928;
|
||||
private static final String DAB_ENTRY_LABEL_2 = "12D";
|
||||
private static final int DAB_ENTRY_FREQUENCY_2 = 229072;
|
||||
private static final int DAB_ENTRY_FREQUENCY_2 = 229_072;
|
||||
private static final String VENDOR_INFO_KEY_1 = "vendorKey1";
|
||||
private static final String VENDOR_INFO_VALUE_1 = "vendorValue1";
|
||||
private static final String VENDOR_INFO_KEY_2 = "vendorKey2";
|
||||
@@ -57,6 +62,50 @@ 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 = 220_352;
|
||||
private static final long TEST_FM_FREQUENCY_VALUE = 92_100;
|
||||
private static final long TEST_VENDOR_ID_VALUE = 9_901;
|
||||
|
||||
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 ProgramSelector.Identifier TEST_FM_FREQUENCY_ID =
|
||||
new ProgramSelector.Identifier(
|
||||
ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, TEST_FM_FREQUENCY_VALUE);
|
||||
private static final ProgramSelector.Identifier TEST_VENDOR_ID =
|
||||
new ProgramSelector.Identifier(
|
||||
ProgramSelector.IDENTIFIER_TYPE_VENDOR_START, TEST_VENDOR_ID_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 ProgramIdentifier TEST_HAL_FM_FREQUENCY_ID =
|
||||
AidlTestUtils.makeHalIdentifier(IdentifierType.AMFM_FREQUENCY_KHZ,
|
||||
TEST_FM_FREQUENCY_VALUE);
|
||||
private static final ProgramIdentifier TEST_HAL_VENDOR_ID =
|
||||
AidlTestUtils.makeHalIdentifier(IdentifierType.VENDOR_START,
|
||||
TEST_VENDOR_ID_VALUE);
|
||||
|
||||
private static final ProgramSelector TEST_DAB_SELECTOR = new ProgramSelector(
|
||||
ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_EXT_ID,
|
||||
new ProgramSelector.Identifier[]{TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID},
|
||||
/* vendorIds= */ null);
|
||||
private static final ProgramSelector TEST_FM_SELECTOR =
|
||||
AidlTestUtils.makeFmSelector(TEST_FM_FREQUENCY_VALUE);
|
||||
|
||||
private static final int TEST_ENABLED_TYPE = Announcement.TYPE_EMERGENCY;
|
||||
private static final int TEST_ANNOUNCEMENT_FREQUENCY = FM_LOWER_LIMIT + FM_SPACING;
|
||||
|
||||
@@ -158,6 +207,246 @@ public final class ConversionUtilsTest {
|
||||
.that(bands[1].getSpacing()).isEqualTo(AM_SPACING);
|
||||
}
|
||||
|
||||
@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() {
|
||||
android.hardware.broadcastradio.ProgramSelector halDabSelector =
|
||||
ConversionUtils.programSelectorToHalProgramSelector(TEST_DAB_SELECTOR);
|
||||
|
||||
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 chunkFromHalProgramListChunk_withValidChunk() {
|
||||
boolean purge = false;
|
||||
boolean complete = true;
|
||||
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 halDabInfo = AidlTestUtils.makeHalProgramInfo(halDabSelector,
|
||||
TEST_HAL_DAB_SID_EXT_ID, TEST_HAL_DAB_FREQUENCY_ID, TEST_SIGNAL_QUALITY);
|
||||
RadioManager.ProgramInfo dabInfo =
|
||||
ConversionUtils.programInfoFromHalProgramInfo(halDabInfo);
|
||||
ProgramListChunk halChunk = AidlTestUtils.makeProgramListChunk(purge, complete,
|
||||
new ProgramInfo[]{halDabInfo},
|
||||
new ProgramIdentifier[]{TEST_HAL_VENDOR_ID, TEST_HAL_FM_FREQUENCY_ID});
|
||||
|
||||
ProgramList.Chunk chunk = ConversionUtils.chunkFromHalProgramListChunk(halChunk);
|
||||
|
||||
expect.withMessage("Purged state of the converted valid program list chunk")
|
||||
.that(chunk.isPurge()).isEqualTo(purge);
|
||||
expect.withMessage("Completion state of the converted valid program list chunk")
|
||||
.that(chunk.isComplete()).isEqualTo(complete);
|
||||
expect.withMessage("Modified program info in the converted valid program list chunk")
|
||||
.that(chunk.getModified()).containsExactly(dabInfo);
|
||||
expect.withMessage("Removed program ides in the converted valid program list chunk")
|
||||
.that(chunk.getRemoved()).containsExactly(TEST_VENDOR_ID, TEST_FM_FREQUENCY_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void chunkFromHalProgramListChunk_withInvalidModifiedProgramInfo() {
|
||||
boolean purge = true;
|
||||
boolean complete = false;
|
||||
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 halDabInfo = AidlTestUtils.makeHalProgramInfo(halDabSelector,
|
||||
TEST_HAL_DAB_SID_EXT_ID, TEST_HAL_DAB_ENSEMBLE_ID, TEST_SIGNAL_QUALITY);
|
||||
ProgramListChunk halChunk = AidlTestUtils.makeProgramListChunk(purge, complete,
|
||||
new ProgramInfo[]{halDabInfo}, new ProgramIdentifier[]{TEST_HAL_FM_FREQUENCY_ID});
|
||||
|
||||
ProgramList.Chunk chunk = ConversionUtils.chunkFromHalProgramListChunk(halChunk);
|
||||
|
||||
expect.withMessage("Purged state of the converted invalid program list chunk")
|
||||
.that(chunk.isPurge()).isEqualTo(purge);
|
||||
expect.withMessage("Completion state of the converted invalid program list chunk")
|
||||
.that(chunk.isComplete()).isEqualTo(complete);
|
||||
expect.withMessage("Modified program info in the converted invalid program list chunk")
|
||||
.that(chunk.getModified()).isEmpty();
|
||||
expect.withMessage("Removed program ids in the converted invalid program list chunk")
|
||||
.that(chunk.getRemoved()).containsExactly(TEST_FM_FREQUENCY_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void programSelectorMeetsSdkVersionRequirement_withLowerVersionId_returnsFalse() {
|
||||
expect.withMessage("Selector %s without required SDK version", TEST_DAB_SELECTOR)
|
||||
.that(ConversionUtils.programSelectorMeetsSdkVersionRequirement(TEST_DAB_SELECTOR,
|
||||
Build.VERSION_CODES.TIRAMISU)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void programSelectorMeetsSdkVersionRequirement_withRequiredVersionId_returnsTrue() {
|
||||
expect.withMessage("Selector %s with required SDK version", TEST_FM_SELECTOR)
|
||||
.that(ConversionUtils.programSelectorMeetsSdkVersionRequirement(TEST_FM_SELECTOR,
|
||||
Build.VERSION_CODES.TIRAMISU)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void programInfoMeetsSdkVersionRequirement_withLowerVersionId_returnsFalse() {
|
||||
RadioManager.ProgramInfo dabProgramInfo = AidlTestUtils.makeProgramInfo(TEST_DAB_SELECTOR,
|
||||
TEST_DAB_SID_EXT_ID, TEST_DAB_FREQUENCY_ID, TEST_SIGNAL_QUALITY);
|
||||
|
||||
expect.withMessage("Program info %s without required SDK version", dabProgramInfo)
|
||||
.that(ConversionUtils.programInfoMeetsSdkVersionRequirement(dabProgramInfo,
|
||||
Build.VERSION_CODES.TIRAMISU)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void programInfoMeetsSdkVersionRequirement_withRequiredVersionId_returnsTrue() {
|
||||
RadioManager.ProgramInfo fmProgramInfo = AidlTestUtils.makeProgramInfo(TEST_FM_SELECTOR,
|
||||
TEST_SIGNAL_QUALITY);
|
||||
|
||||
expect.withMessage("Program info %s with required SDK version", fmProgramInfo)
|
||||
.that(ConversionUtils.programInfoMeetsSdkVersionRequirement(fmProgramInfo,
|
||||
Build.VERSION_CODES.TIRAMISU)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertChunkToTargetSdkVersion_withLowerSdkVersion() {
|
||||
RadioManager.ProgramInfo dabProgramInfo = AidlTestUtils.makeProgramInfo(TEST_DAB_SELECTOR,
|
||||
TEST_DAB_SID_EXT_ID, TEST_DAB_FREQUENCY_ID, TEST_SIGNAL_QUALITY);
|
||||
RadioManager.ProgramInfo fmProgramInfo = AidlTestUtils.makeProgramInfo(TEST_FM_SELECTOR,
|
||||
TEST_SIGNAL_QUALITY);
|
||||
ProgramList.Chunk chunk = new ProgramList.Chunk(/* purge= */ true,
|
||||
/* complete= */ true, Set.of(dabProgramInfo, fmProgramInfo),
|
||||
Set.of(TEST_DAB_SID_EXT_ID, TEST_DAB_ENSEMBLE_ID, TEST_VENDOR_ID));
|
||||
|
||||
ProgramList.Chunk convertedChunk = ConversionUtils.convertChunkToTargetSdkVersion(chunk,
|
||||
Build.VERSION_CODES.TIRAMISU);
|
||||
|
||||
expect.withMessage(
|
||||
"Purged state of the converted program list chunk with lower SDK version")
|
||||
.that(convertedChunk.isPurge()).isEqualTo(chunk.isPurge());
|
||||
expect.withMessage(
|
||||
"Completion state of the converted program list chunk with lower SDK version")
|
||||
.that(convertedChunk.isComplete()).isEqualTo(chunk.isComplete());
|
||||
expect.withMessage(
|
||||
"Modified program info in the converted program list chunk with lower SDK version")
|
||||
.that(convertedChunk.getModified()).containsExactly(fmProgramInfo);
|
||||
expect.withMessage(
|
||||
"Removed program ids in the converted program list chunk with lower SDK version")
|
||||
.that(convertedChunk.getRemoved())
|
||||
.containsExactly(TEST_DAB_ENSEMBLE_ID, TEST_VENDOR_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertChunkToTargetSdkVersion_withRequiredSdkVersion() {
|
||||
RadioManager.ProgramInfo dabProgramInfo = AidlTestUtils.makeProgramInfo(TEST_DAB_SELECTOR,
|
||||
TEST_DAB_SID_EXT_ID, TEST_DAB_FREQUENCY_ID, TEST_SIGNAL_QUALITY);
|
||||
RadioManager.ProgramInfo fmProgramInfo = AidlTestUtils.makeProgramInfo(TEST_FM_SELECTOR,
|
||||
TEST_SIGNAL_QUALITY);
|
||||
ProgramList.Chunk chunk = new ProgramList.Chunk(/* purge= */ true,
|
||||
/* complete= */ true, Set.of(dabProgramInfo, fmProgramInfo),
|
||||
Set.of(TEST_DAB_SID_EXT_ID, TEST_DAB_ENSEMBLE_ID, TEST_VENDOR_ID));
|
||||
|
||||
ProgramList.Chunk convertedChunk = ConversionUtils.convertChunkToTargetSdkVersion(chunk,
|
||||
Build.VERSION_CODES.CUR_DEVELOPMENT);
|
||||
|
||||
expect.withMessage("Converted program list chunk with required SDK version")
|
||||
.that(convertedChunk).isEqualTo(chunk);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void announcementFromHalAnnouncement_typesMatch() {
|
||||
expect.withMessage("Announcement type")
|
||||
|
||||
@@ -26,7 +26,9 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -43,6 +45,8 @@ import android.hardware.radio.ProgramSelector;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.hardware.radio.RadioTuner;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelableException;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
@@ -57,7 +61,6 @@ import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.verification.VerificationWithTimeout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -71,10 +74,10 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
timeout(/* millis= */ 200);
|
||||
private static final int SIGNAL_QUALITY = 1;
|
||||
private static final long AM_FM_FREQUENCY_SPACING = 500;
|
||||
private static final long[] AM_FM_FREQUENCY_LIST = {97500, 98100, 99100};
|
||||
private static final long[] AM_FM_FREQUENCY_LIST = {97_500, 98_100, 99_100};
|
||||
private static final RadioManager.FmBandDescriptor FM_BAND_DESCRIPTOR =
|
||||
new RadioManager.FmBandDescriptor(RadioManager.REGION_ITU_1, RadioManager.BAND_FM,
|
||||
/* lowerLimit= */ 87500, /* upperLimit= */ 108000, /* spacing= */ 100,
|
||||
/* lowerLimit= */ 87_500, /* upperLimit= */ 108_000, /* spacing= */ 100,
|
||||
/* stereo= */ false, /* rds= */ false, /* ta= */ false, /* af= */ false,
|
||||
/* ea= */ false);
|
||||
private static final RadioManager.BandConfig FM_BAND_CONFIG =
|
||||
@@ -199,6 +202,17 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onConfigurationChanged(FM_BAND_CONFIG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConfiguration_forNonCurrentUser_doesNotInvokesCallback() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
|
||||
mTunerSessions[0].setConfiguration(FM_BAND_CONFIG);
|
||||
|
||||
verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
|
||||
.onConfigurationChanged(FM_BAND_CONFIG);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getConfiguration() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
@@ -330,10 +344,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,7 +364,22 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tune_forCurrentUser_doesNotTune() throws Exception {
|
||||
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_forNonCurrentUser_doesNotTune() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
|
||||
@@ -356,6 +392,21 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
.onCurrentProgramInfoChanged(tuneInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tune_withHalHasUnknownError_fails() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
ProgramSelector sel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
|
||||
doThrow(new ServiceSpecificException(Result.UNKNOWN_ERROR))
|
||||
.when(mBroadcastRadioMock).tune(any());
|
||||
|
||||
ParcelableException thrown = assertThrows(ParcelableException.class, () -> {
|
||||
mTunerSessions[0].tune(sel);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for tuning when HAL has unknown error")
|
||||
.that(thrown).hasMessageThat().contains("UNKNOWN_ERROR");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void step_withDirectionUp() throws Exception {
|
||||
long initFreq = AM_FM_FREQUENCY_LIST[1];
|
||||
@@ -390,6 +441,35 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
.onCurrentProgramInfoChanged(stepDownInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void step_forNonCurrentUser_doesNotStep() throws Exception {
|
||||
long initFreq = AM_FM_FREQUENCY_LIST[1];
|
||||
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(initFreq);
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
mHalCurrentInfo = AidlTestUtils.makeHalProgramInfo(
|
||||
ConversionUtils.programSelectorToHalProgramSelector(initialSel), SIGNAL_QUALITY);
|
||||
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
|
||||
mTunerSessions[0].step(/* directionDown= */ true, /* skipSubChannel= */ false);
|
||||
|
||||
verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
|
||||
.onCurrentProgramInfoChanged(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void step_withHalInInvalidState_fails() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
doThrow(new ServiceSpecificException(Result.INVALID_STATE))
|
||||
.when(mBroadcastRadioMock).step(anyBoolean());
|
||||
|
||||
IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> {
|
||||
mTunerSessions[0].step(/* directionDown= */ true, /* skipSubChannel= */ false);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for stepping when HAL is in invalid state")
|
||||
.that(thrown).hasMessageThat().contains("INVALID_STATE");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seek_withDirectionUp() throws Exception {
|
||||
long initFreq = AM_FM_FREQUENCY_LIST[2];
|
||||
@@ -432,10 +512,43 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
ConversionUtils.programSelectorToHalProgramSelector(initialSel), SIGNAL_QUALITY);
|
||||
|
||||
mTunerSessions[0].seek(/* directionDown= */ true, /* skipSubChannel= */ false);
|
||||
|
||||
verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT)
|
||||
.onCurrentProgramInfoChanged(seekUpInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seek_forNonCurrentUser_doesNotSeek() throws Exception {
|
||||
long initFreq = AM_FM_FREQUENCY_LIST[2];
|
||||
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(initFreq);
|
||||
RadioManager.ProgramInfo seekUpInfo = AidlTestUtils.makeProgramInfo(
|
||||
AidlTestUtils.makeFmSelector(getSeekFrequency(initFreq, /* seekDown= */ true)),
|
||||
SIGNAL_QUALITY);
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
mHalCurrentInfo = AidlTestUtils.makeHalProgramInfo(
|
||||
ConversionUtils.programSelectorToHalProgramSelector(initialSel), SIGNAL_QUALITY);
|
||||
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
|
||||
mTunerSessions[0].seek(/* directionDown= */ true, /* skipSubChannel= */ false);
|
||||
|
||||
verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
|
||||
.onCurrentProgramInfoChanged(seekUpInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seek_withHalHasInternalError_fails() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
doThrow(new ServiceSpecificException(Result.INTERNAL_ERROR))
|
||||
.when(mBroadcastRadioMock).seek(anyBoolean(), anyBoolean());
|
||||
|
||||
ParcelableException thrown = assertThrows(ParcelableException.class, () -> {
|
||||
mTunerSessions[0].seek(/* directionDown= */ true, /* skipSubChannel= */ false);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for seeking when HAL has internal error")
|
||||
.that(thrown).hasMessageThat().contains("INTERNAL_ERROR");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancel() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
@@ -447,6 +560,32 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
verify(mBroadcastRadioMock).cancel();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancel_forNonCurrentUser_doesNotCancel() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
|
||||
mTunerSessions[0].tune(initialSel);
|
||||
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
|
||||
mTunerSessions[0].cancel();
|
||||
|
||||
verify(mBroadcastRadioMock, never()).cancel();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancel_whenHalThrowsRemoteException_fails() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
String exceptionMessage = "HAL service died.";
|
||||
doThrow(new RemoteException(exceptionMessage)).when(mBroadcastRadioMock).cancel();
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
|
||||
mTunerSessions[0].cancel();
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for canceling when HAL throws remote exception")
|
||||
.that(thrown).hasMessageThat().contains(exceptionMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getImage_withInvalidId_throwsIllegalArgumentException() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
@@ -470,6 +609,21 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
assertWithMessage("Null image").that(imageTest).isEqualTo(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getImage_whenHalThrowsException_fails() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
String exceptionMessage = "HAL service died.";
|
||||
when(mBroadcastRadioMock.getImage(anyInt()))
|
||||
.thenThrow(new RemoteException(exceptionMessage));
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
|
||||
mTunerSessions[0].getImage(/* id= */ 1);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for getting image when HAL throws remote exception")
|
||||
.that(thrown).hasMessageThat().contains(exceptionMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startBackgroundScan() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
@@ -479,6 +633,16 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onBackgroundScanComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startBackgroundScan_forNonCurrentUser_doesNotInvokesCallback() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
|
||||
mTunerSessions[0].startBackgroundScan();
|
||||
|
||||
verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0)).onBackgroundScanComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopProgramListUpdates() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
@@ -491,6 +655,19 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
verify(mBroadcastRadioMock).stopProgramListUpdates();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stopProgramListUpdates_forNonCurrentUser_doesNotStopUpdates() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
ProgramList.Filter aidlFilter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
|
||||
/* includeCategories= */ true, /* excludeModifications= */ false);
|
||||
mTunerSessions[0].startProgramListUpdates(aidlFilter);
|
||||
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
|
||||
mTunerSessions[0].stopProgramListUpdates();
|
||||
|
||||
verify(mBroadcastRadioMock, never()).stopProgramListUpdates();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSupported_withUnsupportedFlag_returnsFalse() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
@@ -546,6 +723,17 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
verify(mBroadcastRadioMock).setConfigFlag(flag, /* value= */ false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConfigFlag_forNonCurrentUser_doesNotSetConfigFlag() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
int flag = UNSUPPORTED_CONFIG_FLAG + 1;
|
||||
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
|
||||
mTunerSessions[0].setConfigFlag(flag, /* value= */ true);
|
||||
|
||||
verify(mBroadcastRadioMock, never()).setConfigFlag(flag, /* value= */ true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSet_withUnsupportedFlag_throwsRuntimeException()
|
||||
throws Exception {
|
||||
@@ -556,7 +744,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
mTunerSessions[0].isConfigFlagSet(flag);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for check if unsupported flag %s is set", flag)
|
||||
assertWithMessage("Exception for checking if unsupported flag %s is set", flag)
|
||||
.that(thrown).hasMessageThat().contains("isConfigFlagSet: NOT_SUPPORTED");
|
||||
}
|
||||
|
||||
@@ -573,6 +761,20 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
.that(isSet).isEqualTo(expectedConfigFlagValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSet_whenHalThrowsRemoteException_fails() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
int flag = UNSUPPORTED_CONFIG_FLAG + 1;
|
||||
doThrow(new RemoteException()).when(mBroadcastRadioMock).isConfigFlagSet(anyInt());
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
|
||||
mTunerSessions[0].isConfigFlagSet(flag);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for checking config flag when HAL throws remote exception")
|
||||
.that(thrown).hasMessageThat().contains("Failed to check flag");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setParameters_withMockParameters() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
@@ -585,17 +787,59 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
ConversionUtils.vendorInfoToHalVendorKeyValues(parametersSet));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setParameters_forNonCurrentUser_doesNotSetParameters() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
Map<String, String> parametersSet = Map.of("mockParam1", "mockValue1",
|
||||
"mockParam2", "mockValue2");
|
||||
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
|
||||
mTunerSessions[0].setParameters(parametersSet);
|
||||
|
||||
verify(mBroadcastRadioMock, never()).setParameters(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setParameters_whenHalThrowsRemoteException_fails() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
Map<String, String> parametersSet = Map.of("mockParam1", "mockValue1",
|
||||
"mockParam2", "mockValue2");
|
||||
String exceptionMessage = "HAL service died.";
|
||||
when(mBroadcastRadioMock.setParameters(any()))
|
||||
.thenThrow(new RemoteException(exceptionMessage));
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
|
||||
mTunerSessions[0].setParameters(parametersSet);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for setting parameters when HAL throws remote exception")
|
||||
.that(thrown).hasMessageThat().contains(exceptionMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getParameters_withMockKeys() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
List<String> parameterKeys = new ArrayList<>(2);
|
||||
parameterKeys.add("mockKey1");
|
||||
parameterKeys.add("mockKey2");
|
||||
List<String> parameterKeys = List.of("mockKey1", "mockKey2");
|
||||
|
||||
mTunerSessions[0].getParameters(parameterKeys);
|
||||
|
||||
verify(mBroadcastRadioMock).getParameters(
|
||||
parameterKeys.toArray(new String[0]));
|
||||
verify(mBroadcastRadioMock).getParameters(parameterKeys.toArray(new String[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getParameters_whenServiceThrowsRemoteException_fails() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
List<String> parameterKeys = List.of("mockKey1", "mockKey2");
|
||||
String exceptionMessage = "HAL service died.";
|
||||
when(mBroadcastRadioMock.getParameters(any()))
|
||||
.thenThrow(new RemoteException(exceptionMessage));
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
|
||||
mTunerSessions[0].getParameters(parameterKeys);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for getting parameters when HAL throws remote exception")
|
||||
.that(thrown).hasMessageThat().contains(exceptionMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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) {
|
||||
@@ -547,10 +627,22 @@ final class ConversionUtils {
|
||||
if (isAtLeastU(targetSdkVersion)) {
|
||||
return chunk;
|
||||
}
|
||||
Set<RadioManager.ProgramInfo> modified = chunk.getModified();
|
||||
modified.removeIf(info -> !programInfoMeetsSdkVersionRequirement(info, targetSdkVersion));
|
||||
Set<ProgramSelector.Identifier> removed = chunk.getRemoved();
|
||||
removed.removeIf(id -> isNewIdentifierInU(id));
|
||||
Set<RadioManager.ProgramInfo> modified = new ArraySet<>();
|
||||
Iterator<RadioManager.ProgramInfo> modifiedIterator = chunk.getModified().iterator();
|
||||
while (modifiedIterator.hasNext()) {
|
||||
RadioManager.ProgramInfo info = modifiedIterator.next();
|
||||
if (programInfoMeetsSdkVersionRequirement(info, targetSdkVersion)) {
|
||||
modified.add(info);
|
||||
}
|
||||
}
|
||||
Set<ProgramSelector.Identifier> removed = new ArraySet<>();
|
||||
Iterator<ProgramSelector.Identifier> removedIterator = chunk.getRemoved().iterator();
|
||||
while (removedIterator.hasNext()) {
|
||||
ProgramSelector.Identifier id = removedIterator.next();
|
||||
if (!isNewIdentifierInU(id)) {
|
||||
removed.add(id);
|
||||
}
|
||||
}
|
||||
return new ProgramList.Chunk(chunk.isPurge(), chunk.isComplete(), modified, removed);
|
||||
}
|
||||
|
||||
@@ -558,7 +650,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)
|
||||
);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user