Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ab42d3a authored by Weilin Xu's avatar Weilin Xu
Browse files

Add missing unit tests for bcradio service

Added missing unit tests for tuner session, radio module and
conversion utils in broadcast radio service. Also fixed invalid
identifier handling in programSelectorFromHalProgramSelector.

Bug: 282031772
Test: atest BroadcastRadioTests
Flag: TEST_ONLY
Change-Id: Ic2709eb8fc039433585dc2a68505f08c2f441e9e
parent 8644138d
Loading
Loading
Loading
Loading
+121 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.hardware.broadcastradio.ConfigFlag;
import android.hardware.broadcastradio.DabTableEntry;
import android.hardware.broadcastradio.IdentifierType;
import android.hardware.broadcastradio.Metadata;
import android.hardware.broadcastradio.ProgramFilter;
import android.hardware.broadcastradio.ProgramIdentifier;
import android.hardware.broadcastradio.ProgramInfo;
import android.hardware.broadcastradio.Properties;
@@ -41,6 +42,7 @@ import android.hardware.radio.RadioMetadata;
import android.hardware.radio.UniqueProgramIdentifier;
import android.os.ServiceSpecificException;
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.ArraySet;

import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
@@ -93,6 +95,11 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase {
    private static final long TEST_HD_LOCATION_VALUE =  0x4E647007665CF6L;
    private static final long TEST_VENDOR_ID_VALUE = 9_901;

    private static final ProgramSelector.Identifier TEST_INVALID_ID =
            new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_INVALID, 1);
    private static final ProgramIdentifier TEST_HAL_INVALID_ID =
            AidlTestUtils.makeHalIdentifier(IdentifierType.INVALID, 1);

    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);
@@ -139,7 +146,7 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase {
    private static final int TEST_ANNOUNCEMENT_FREQUENCY = FM_LOWER_LIMIT + FM_SPACING;

    private static final RadioManager.ModuleProperties MODULE_PROPERTIES =
            convertToModuleProperties();
            createModuleProperties();
    private static final Announcement ANNOUNCEMENT =
            ConversionUtils.announcementFromHalAnnouncement(
                    AidlTestUtils.makeAnnouncement(TEST_ENABLED_TYPE, TEST_ANNOUNCEMENT_FREQUENCY));
@@ -290,6 +297,37 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase {
                .that(bands[1].getSpacing()).isEqualTo(AM_SPACING);
    }

    @Test
    public void propertiesFromHalProperties_withoutAmFmAndDabConfigs() {
        RadioManager.ModuleProperties properties = createModuleProperties(/* amFmConfig= */ null,
                new DabTableEntry[]{});

        expect.withMessage("Empty AM/FM config")
                .that(properties.getBands()).asList().isEmpty();
        expect.withMessage("Empty DAB config")
                .that(properties.getDabFrequencyTable()).isNull();
    }

    @Test
    public void propertiesFromHalProperties_withInvalidBand() {
        AmFmRegionConfig amFmRegionConfig = new AmFmRegionConfig();
        amFmRegionConfig.ranges = new AmFmBandRange[]{createAmFmBandRange(/* lowerBound= */ 50000,
                /* upperBound= */ 60000, /* spacing= */ 10),
                createAmFmBandRange(FM_LOWER_LIMIT, FM_UPPER_LIMIT, FM_SPACING)};

        RadioManager.ModuleProperties properties = createModuleProperties(amFmRegionConfig,
                new DabTableEntry[]{});

        RadioManager.BandDescriptor[] bands = properties.getBands();
        expect.withMessage("Band descriptors").that(bands).hasLength(1);
        expect.withMessage("FM band frequency lower limit")
                .that(bands[0].getLowerLimit()).isEqualTo(FM_LOWER_LIMIT);
        expect.withMessage("FM band frequency upper limit")
                .that(bands[0].getUpperLimit()).isEqualTo(FM_UPPER_LIMIT);
        expect.withMessage("FM band frequency spacing")
                .that(bands[0].getSpacing()).isEqualTo(FM_SPACING);
    }

    @Test
    public void identifierToHalProgramIdentifier_withDabId() {
        ProgramIdentifier halDabId =
@@ -357,6 +395,13 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase {
                .that(hdLocationId).isNull();
    }

    @Test
    public void identifierFromHalProgramIdentifier_withInvalidIdentifier() {
        expect.withMessage("Identifier converted from invalid HAL identifier")
                .that(ConversionUtils.identifierFromHalProgramIdentifier(TEST_HAL_INVALID_ID))
                .isNull();
    }

    @Test
    public void programSelectorToHalProgramSelector_withValidSelector() {
        android.hardware.broadcastradio.ProgramSelector halDabSelector =
@@ -369,6 +414,23 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase {
                .containsExactly(TEST_HAL_DAB_FREQUENCY_ID, TEST_HAL_DAB_ENSEMBLE_ID);
    }

    @Test
    public void programSelectorToHalProgramSelector_withInvalidSecondaryId() {
        ProgramSelector dabSelector = new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB,
                TEST_DAB_SID_EXT_ID, new ProgramSelector.Identifier[]{TEST_INVALID_ID,
                    TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID}, /* vendorIds= */ null);

        android.hardware.broadcastradio.ProgramSelector halDabSelector =
                ConversionUtils.programSelectorToHalProgramSelector(dabSelector);

        expect.withMessage("Primary identifier of converted HAL DAB selector with invalid "
                        + "secondary id").that(halDabSelector.primaryId)
                .isEqualTo(TEST_HAL_DAB_SID_EXT_ID);
        expect.withMessage("Secondary identifiers of converted HAL DAB selector with "
                        + "invalid secondary id").that(halDabSelector.secondaryIds).asList()
                .containsExactly(TEST_HAL_DAB_FREQUENCY_ID, TEST_HAL_DAB_ENSEMBLE_ID);
    }

    @Test
    public void programSelectorFromHalProgramSelector_withValidSelector() {
        android.hardware.broadcastradio.ProgramSelector halDabSelector =
@@ -385,6 +447,33 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase {
                .containsExactly(TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID);
    }

    @Test
    public void programSelectorFromHalProgramSelector_withInvalidSelector() {
        android.hardware.broadcastradio.ProgramSelector invalidSelector =
                AidlTestUtils.makeHalSelector(TEST_HAL_INVALID_ID, new ProgramIdentifier[]{});

        expect.withMessage("Selector converted from invalid HAL selector")
                .that(ConversionUtils.programSelectorFromHalProgramSelector(invalidSelector))
                .isNull();
    }

    @Test
    public void programSelectorFromHalProgramSelector_withInvalidSecondaryId() {
        android.hardware.broadcastradio.ProgramSelector halDabSelector =
                AidlTestUtils.makeHalSelector(TEST_HAL_DAB_SID_EXT_ID, new ProgramIdentifier[]{
                        TEST_HAL_INVALID_ID, TEST_HAL_DAB_ENSEMBLE_ID, TEST_HAL_DAB_FREQUENCY_ID});

        ProgramSelector dabSelector =
                ConversionUtils.programSelectorFromHalProgramSelector(halDabSelector);

        expect.withMessage("Primary identifier of converted DAB selector with invalid "
                        + "secondary id").that(dabSelector.getPrimaryId())
                .isEqualTo(TEST_DAB_SID_EXT_ID);
        expect.withMessage("Secondary identifiers of converted DAB selector with invalid "
                        + "secondary id").that(dabSelector.getSecondaryIds()).asList()
                .containsExactly(TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID);
    }

    @Test
    public void programInfoFromHalProgramInfo_withValidProgramInfo() {
        android.hardware.broadcastradio.ProgramSelector halDabSelector =
@@ -628,11 +717,41 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase {
                .that(Utils.getBand(/* freq= */ 110000)).isEqualTo(Utils.FrequencyBand.UNKNOWN);
    }

    private static RadioManager.ModuleProperties convertToModuleProperties() {
    @Test
    public void filterToHalProgramFilter_withNullFilter() {
        ProgramFilter filter = ConversionUtils.filterToHalProgramFilter(null);

        expect.withMessage("Filter identifier types").that(filter.identifierTypes)
                .asList().isEmpty();
        expect.withMessage("Filter identifiers").that(filter.identifiers).asList()
                .isEmpty();
    }

    @Test
    public void filterToHalProgramFilter_withInvalidIdentifier() {
        Set<ProgramSelector.Identifier> identifiers =
                new ArraySet<ProgramSelector.Identifier>(2);
        identifiers.add(TEST_INVALID_ID);
        identifiers.add(TEST_DAB_SID_EXT_ID);
        ProgramList.Filter filter = new ProgramList.Filter(/* identifierTypes */ new ArraySet<>(),
                identifiers, /* includeCategories= */ true, /* excludeModifications= */ false);
        ProgramFilter halFilter = ConversionUtils.filterToHalProgramFilter(filter);

        expect.withMessage("Filter identifiers with invalid ones removed")
                .that(halFilter.identifiers).asList().containsExactly(
                        ConversionUtils.identifierToHalProgramIdentifier(TEST_DAB_SID_EXT_ID));
    }

    private static RadioManager.ModuleProperties createModuleProperties() {
        AmFmRegionConfig amFmConfig = createAmFmRegionConfig();
        DabTableEntry[] dabTableEntries = new DabTableEntry[]{
                createDabTableEntry(DAB_ENTRY_LABEL_1, DAB_ENTRY_FREQUENCY_1),
                createDabTableEntry(DAB_ENTRY_LABEL_2, DAB_ENTRY_FREQUENCY_2)};
        return createModuleProperties(amFmConfig, dabTableEntries);
    }

    private static RadioManager.ModuleProperties createModuleProperties(
            AmFmRegionConfig amFmConfig, DabTableEntry[] dabTableEntries) {
        Properties properties = createHalProperties();

        return ConversionUtils.propertiesFromHalProperties(TEST_ID, TEST_SERVICE_NAME, properties,
+24 −6
Original line number Diff line number Diff line
@@ -16,13 +16,12 @@

package com.android.server.broadcastradio.aidl;

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.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -32,9 +31,13 @@ import android.hardware.radio.Announcement;
import android.hardware.radio.IAnnouncementListener;
import android.hardware.radio.ICloseHandle;
import android.hardware.radio.RadioManager;
import android.os.ParcelableException;
import android.os.RemoteException;

import com.google.common.truth.Expect;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -50,6 +53,9 @@ public final class RadioModuleTest {
    private static final RadioManager.ModuleProperties TEST_MODULE_PROPERTIES =
            AidlTestUtils.makeDefaultModuleProperties();

    @Rule
    public final Expect mExpect = Expect.create();

    // Mocks
    @Mock
    private IBroadcastRadio mBroadcastRadioMock;
@@ -77,13 +83,13 @@ public final class RadioModuleTest {

    @Test
    public void getService() {
        assertWithMessage("Service of radio module")
        mExpect.withMessage("Service of radio module")
                .that(mRadioModule.getService()).isEqualTo(mBroadcastRadioMock);
    }

    @Test
    public void getProperties() {
        assertWithMessage("Module properties of radio module")
        mExpect.withMessage("Module properties of radio module")
                .that(mRadioModule.getProperties()).isEqualTo(TEST_MODULE_PROPERTIES);
    }

@@ -93,7 +99,7 @@ public final class RadioModuleTest {

        Bitmap imageTest = mRadioModule.getImage(imageId);

        assertWithMessage("Image from radio module").that(imageTest).isNull();
        mExpect.withMessage("Image from radio module").that(imageTest).isNull();
    }

    @Test
@@ -104,7 +110,7 @@ public final class RadioModuleTest {
            mRadioModule.getImage(invalidImageId);
        });

        assertWithMessage("Exception for getting image with invalid ID")
        mExpect.withMessage("Exception for getting image with invalid ID")
                .that(thrown).hasMessageThat().contains("Image ID is missing");
    }

@@ -116,6 +122,18 @@ public final class RadioModuleTest {
                .registerAnnouncementListener(any(), eq(new byte[]{TEST_ENABLED_TYPE}));
    }

    @Test
    public void addAnnouncementListener_whenHalThrowsRemoteException() throws Exception {
        doThrow(new RuntimeException("HAL service died")).when(mBroadcastRadioMock)
                .registerAnnouncementListener(any(), any());

        ParcelableException thrown = assertThrows(ParcelableException.class, () ->
                mRadioModule.addAnnouncementListener(mListenerMock, new int[]{TEST_ENABLED_TYPE}));

        mExpect.withMessage("Exception for adding announcement listener when HAL service died")
                .that(thrown).hasMessageThat().contains("unknown error");
    }

    @Test
    public void onListUpdate_forAnnouncementListener() throws Exception {
        android.hardware.broadcastradio.Announcement halAnnouncement =
+71 −0
Original line number Diff line number Diff line
@@ -420,6 +420,19 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
                .that(thrown).hasMessageThat().contains("UNKNOWN_ERROR");
    }

    @Test
    public void tune_withClosedTuner_fails() throws Exception {
        openAidlClients(/* numClients= */ 1);
        ProgramSelector sel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
        mTunerSessions[0].close();

        IllegalStateException thrown = assertThrows(IllegalStateException.class,
                () -> mTunerSessions[0].tune(sel));

        expect.withMessage("Exception for tuning on closed tuner").that(thrown).hasMessageThat()
                .contains("Tuner is closed");
    }

    @Test
    public void step_withDirectionUp() throws Exception {
        long initFreq = AM_FM_FREQUENCY_LIST[1];
@@ -1148,6 +1161,20 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
                .onCurrentProgramInfoChanged(any());
    }

    @Test
    public void onCurrentProgramInfoChanged_withLowerSdkVersion_doesNotInvokesCallback()
            throws Exception {
        doReturn(false).when(() -> CompatChanges.isChangeEnabled(
                eq(ConversionUtils.RADIO_U_VERSION_REQUIRED), anyInt()));
        openAidlClients(/* numClients= */ 1);

        mHalTunerCallback.onCurrentProgramInfoChanged(
                AidlTestUtils.programInfoToHalProgramInfo(TEST_DAB_INFO));

        verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).never())
                .onCurrentProgramInfoChanged(any());
    }

    @Test
    public void onTuneFailed_forTunerCallback() throws Exception {
        int numSessions = 3;
@@ -1164,6 +1191,20 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
        }
    }

    @Test
    public void onTuneFailed_withLowerSdkVersion_doesNotInvokesCallback()
            throws Exception {
        doReturn(false).when(() -> CompatChanges.isChangeEnabled(
                eq(ConversionUtils.RADIO_U_VERSION_REQUIRED), anyInt()));
        openAidlClients(/* numClients= */ 1);

        mHalTunerCallback.onTuneFailed(Result.CANCELED,
                ConversionUtils.programSelectorToHalProgramSelector(TEST_DAB_SELECTOR));

        verify(mAidlTunerCallbackMocks[0], after(CALLBACK_TIMEOUT_MS).never())
                .onTuneFailed(anyInt(), any());
    }

    @Test
    public void onAntennaStateChange_forTunerCallback() throws Exception {
        int numSessions = 3;
@@ -1231,6 +1272,36 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
        }
    }

    @Test
    public void openSession_withNonNullAntennaState() throws Exception {
        boolean antennaConnected = false;
        android.hardware.radio.ITunerCallback callback =
                mock(android.hardware.radio.ITunerCallback.class);
        openAidlClients(/* numClients= */ 1);
        mHalTunerCallback.onAntennaStateChange(antennaConnected);
        verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onAntennaState(antennaConnected);

        mRadioModule.openSession(callback);

        verify(callback, CALLBACK_TIMEOUT).onAntennaState(antennaConnected);
    }

    @Test
    public void openSession_withNonNullCurrentProgramInfo() throws Exception {
        openAidlClients(/* numClients= */ 1);
        ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
        RadioManager.ProgramInfo tuneInfo = AidlTestUtils.makeProgramInfo(initialSel,
                SIGNAL_QUALITY);
        mTunerSessions[0].tune(initialSel);
        verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onCurrentProgramInfoChanged(tuneInfo);
        android.hardware.radio.ITunerCallback callback =
                mock(android.hardware.radio.ITunerCallback.class);

        mRadioModule.openSession(callback);

        verify(callback, CALLBACK_TIMEOUT).onCurrentProgramInfoChanged(tuneInfo);
    }

    private void openAidlClients(int numClients) throws Exception {
        mAidlTunerCallbackMocks = new android.hardware.radio.ITunerCallback[numClients];
        mTunerSessions = new TunerSession[numClients];
+28 −4
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.hardware.broadcastradio.V2_0.AmFmRegionConfig;
import android.hardware.broadcastradio.V2_0.DabTableEntry;
import android.hardware.broadcastradio.V2_0.IdentifierType;
import android.hardware.broadcastradio.V2_0.Properties;
import android.hardware.broadcastradio.V2_0.VendorKeyValue;
import android.hardware.radio.Announcement;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
@@ -148,6 +147,26 @@ public final class ConvertTest {
                .that(bands[1].getSpacing()).isEqualTo(AM_SPACING);
    }

    @Test
    public void propertiesFromHalProperties_withInvalidBand() {
        AmFmRegionConfig amFmRegionConfig = new AmFmRegionConfig();
        amFmRegionConfig.ranges = new ArrayList<>(Arrays.asList(createAmFmBandRange(
                /* lowerBound= */ 50000, /* upperBound= */ 60000, /* spacing= */ 10),
                createAmFmBandRange(FM_LOWER_LIMIT, FM_UPPER_LIMIT, FM_SPACING)));

        RadioManager.ModuleProperties properties = convertToModuleProperties(amFmRegionConfig,
                new ArrayList<>());

        RadioManager.BandDescriptor[] bands = properties.getBands();
        expect.withMessage("Band descriptors").that(bands).hasLength(1);
        expect.withMessage("FM band frequency lower limit")
                .that(bands[0].getLowerLimit()).isEqualTo(FM_LOWER_LIMIT);
        expect.withMessage("FM band frequency upper limit")
                .that(bands[0].getUpperLimit()).isEqualTo(FM_UPPER_LIMIT);
        expect.withMessage("FM band frequency spacing")
                .that(bands[0].getSpacing()).isEqualTo(FM_SPACING);
    }

    @Test
    public void announcementFromHalAnnouncement_typesMatch() {
        expect.withMessage("Announcement type")
@@ -184,15 +203,20 @@ public final class ConvertTest {
        List<DabTableEntry> dabTableEntries = Arrays.asList(
                createDabTableEntry(DAB_ENTRY_LABEL_1, DAB_ENTRY_FREQUENCY_1),
                createDabTableEntry(DAB_ENTRY_LABEL_2, DAB_ENTRY_FREQUENCY_2));
        Properties properties = createHalProperties();

        return convertToModuleProperties(amFmConfig, dabTableEntries);
    }

    private static RadioManager.ModuleProperties convertToModuleProperties(
            AmFmRegionConfig amFmConfig, List<DabTableEntry> dabTableEntries) {
        Properties properties = createHalProperties();
        return Convert.propertiesFromHal(TEST_ID, TEST_SERVICE_NAME, properties,
                amFmConfig, dabTableEntries);
    }

    private static AmFmRegionConfig createAmFmRegionConfig() {
        AmFmRegionConfig amFmRegionConfig = new AmFmRegionConfig();
        amFmRegionConfig.ranges = new ArrayList<AmFmBandRange>(Arrays.asList(
        amFmRegionConfig.ranges = new ArrayList<>(Arrays.asList(
                createAmFmBandRange(FM_LOWER_LIMIT, FM_UPPER_LIMIT, FM_SPACING),
                createAmFmBandRange(AM_LOWER_LIMIT, AM_UPPER_LIMIT, AM_SPACING)));
        return amFmRegionConfig;
@@ -222,7 +246,7 @@ public final class ConvertTest {
        halProperties.product = TEST_PRODUCT;
        halProperties.version = TEST_VERSION;
        halProperties.serial = TEST_SERIAL;
        halProperties.vendorInfo = new ArrayList<VendorKeyValue>(Arrays.asList(
        halProperties.vendorInfo = new ArrayList<>(Arrays.asList(
                TestUtils.makeVendorKeyValue(VENDOR_INFO_KEY_1, VENDOR_INFO_VALUE_1),
                TestUtils.makeVendorKeyValue(VENDOR_INFO_KEY_2, VENDOR_INFO_VALUE_2)));
        return halProperties;
+89 −28

File changed.

Preview size limit exceeded, changes collapsed.

Loading