summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java39
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java13
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java174
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java242
-rw-r--r--services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java20
5 files changed, 431 insertions, 57 deletions
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
index 3037f345b5a3..82db716fcdc2 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
@@ -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,18 @@ 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) {
@@ -87,21 +89,6 @@ final class AidlTestUtils {
return hwSelector;
}
- 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 ProgramInfo makeHalProgramInfo(
android.hardware.broadcastradio.ProgramSelector hwSel, int hwSignalQuality) {
return makeHalProgramInfo(hwSel, hwSel.primaryId, hwSel.primaryId, hwSignalQuality);
@@ -121,6 +108,16 @@ final class AidlTestUtils {
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;
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java
index f4040825e9a7..98103f6eddd3 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java
@@ -173,6 +173,19 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
}
@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();
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
index 6604d2aea7c1..710c150c006c 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
@@ -22,9 +22,11 @@ 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;
@@ -35,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";
@@ -62,7 +65,10 @@ public final class ConversionUtilsTest {
private static final int TEST_SIGNAL_QUALITY = 1;
private static final long TEST_DAB_DMB_SID_EXT_VALUE = 0xA000000111L;
private static final long TEST_DAB_ENSEMBLE_VALUE = 0x1001;
- private static final long TEST_DAB_FREQUENCY_VALUE = 220352;
+ private static final 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);
@@ -72,6 +78,13 @@ public final class ConversionUtilsTest {
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 =
@@ -79,6 +92,19 @@ public final class ConversionUtilsTest {
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;
@@ -200,13 +226,8 @@ public final class ConversionUtilsTest {
@Test
public void programSelectorToHalProgramSelector_withValidSelector() {
- ProgramSelector dabSelector = new ProgramSelector(
- ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_EXT_ID,
- new ProgramSelector.Identifier[]{TEST_DAB_ENSEMBLE_ID, TEST_DAB_FREQUENCY_ID},
- new long[0]);
-
android.hardware.broadcastradio.ProgramSelector halDabSelector =
- ConversionUtils.programSelectorToHalProgramSelector(dabSelector);
+ ConversionUtils.programSelectorToHalProgramSelector(TEST_DAB_SELECTOR);
expect.withMessage("Primary identifier of converted HAL DAB selector")
.that(halDabSelector.primaryId).isEqualTo(TEST_HAL_DAB_SID_EXT_ID);
@@ -297,27 +318,136 @@ public final class ConversionUtilsTest {
}
@Test
- public void programSelectorMeetsSdkVersionRequirement_withLowerVersionId_returnsFalse() {
- ProgramSelector dabSelector = new ProgramSelector(
- ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_EXT_ID,
- new ProgramSelector.Identifier[]{TEST_DAB_ENSEMBLE_ID, TEST_DAB_FREQUENCY_ID},
- new long[0]);
+ 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);
+ }
- expect.withMessage("Selector %s not meeting required SDK version", dabSelector)
- .that(ConversionUtils.programSelectorMeetsSdkVersionRequirement(dabSelector,
+ @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() {
- ProgramSelector fmSelector = AidlTestUtils.makeFmSelector(/* freq= */ 97100);
+ 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("Selector %s meeting required SDK version", fmSelector)
- .that(ConversionUtils.programSelectorMeetsSdkVersionRequirement(fmSelector,
+ 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")
.that(ANNOUNCEMENT.getType()).isEqualTo(TEST_ENABLED_TYPE);
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
index 201a50f49f88..d7723acf6f05 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
@@ -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 =
@@ -200,6 +203,17 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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);
mTunerSessions[0].setConfiguration(FM_BAND_CONFIG);
@@ -365,7 +379,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@Test
- public void tune_forCurrentUser_doesNotTune() throws Exception {
+ public void tune_forNonCurrentUser_doesNotTune() throws Exception {
openAidlClients(/* numClients= */ 1);
doReturn(false).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
@@ -379,6 +393,21 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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];
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(initFreq);
@@ -413,6 +442,35 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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];
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(initFreq);
@@ -454,11 +512,44 @@ 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);
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
@@ -470,6 +561,32 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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);
int imageId = IBroadcastRadio.INVALID_IMAGE;
@@ -493,6 +610,21 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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);
@@ -502,6 +634,16 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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);
ProgramList.Filter aidlFilter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(),
@@ -514,6 +656,19 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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);
int flag = UNSUPPORTED_CONFIG_FLAG;
@@ -569,6 +724,17 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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 {
openAidlClients(/* numClients= */ 1);
@@ -578,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");
}
@@ -596,6 +762,20 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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);
Map<String, String> parametersSet = Map.of("mockParam1", "mockValue1",
@@ -608,16 +788,58 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@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
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
index d580d5ce8fa6..c0a238feb9b5 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
@@ -627,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);
}