Merge changes I76cd338d,I5530c5b4
* changes: Add unit tests for HIDL broadcast radio service Add unit tests for radio HIDL tuner and module
This commit is contained in:
@@ -20,9 +20,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -18,9 +18,9 @@ package com.android.server.broadcastradio;
|
||||
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@@ -31,6 +31,16 @@ final class AidlTestUtils {
|
||||
throw new UnsupportedOperationException("AidlTestUtils class is noninstantiable");
|
||||
}
|
||||
|
||||
static RadioManager.ModuleProperties makeDefaultModuleProperties() {
|
||||
return new RadioManager.ModuleProperties(
|
||||
/* id= */ 0, /* serviceName= */ "", /* classId= */ 0, /* implementor= */ "",
|
||||
/* product= */ "", /* version= */ "", /* serial= */ "", /* numTuners= */ 0,
|
||||
/* numAudioSources= */ 0, /* isInitializationRequired= */ false,
|
||||
/* isCaptureSupported= */ false, /* bands= */ null,
|
||||
/* isBgScanSupported= */ false, new int[] {}, new int[] {},
|
||||
/* dabFrequencyTable= */ null, /* vendorInfo= */ null);
|
||||
}
|
||||
|
||||
static RadioManager.ProgramInfo makeProgramInfo(ProgramSelector selector, int signalQuality) {
|
||||
return new RadioManager.ProgramInfo(selector,
|
||||
selector.getPrimaryId(), selector.getPrimaryId(), /* relatedContents= */ null,
|
||||
|
||||
@@ -122,7 +122,7 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
|
||||
createBroadcastRadioService();
|
||||
|
||||
ITuner session = mBroadcastRadioService.openSession(FM_RADIO_MODULE_ID,
|
||||
/*legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock);
|
||||
/* legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock);
|
||||
|
||||
assertWithMessage("Session opened in FM radio module")
|
||||
.that(session).isEqualTo(mFmTunerSessionMock);
|
||||
@@ -133,7 +133,7 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
|
||||
createBroadcastRadioService();
|
||||
|
||||
ITuner session = mBroadcastRadioService.openSession(DAB_RADIO_MODULE_ID + 1,
|
||||
/*legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock);
|
||||
/* legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock);
|
||||
|
||||
assertWithMessage("Session opened with id not found").that(session).isNull();
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@ 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.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -48,14 +48,7 @@ public final class RadioModuleTest {
|
||||
|
||||
private static final int TEST_ENABLED_TYPE = Announcement.TYPE_EVENT;
|
||||
private static final RadioManager.ModuleProperties TEST_MODULE_PROPERTIES =
|
||||
new RadioManager.ModuleProperties(/* id= */ 0, /* serviceName= */ "", /* classId= */ 0,
|
||||
/* implementor= */ "", /* product= */ "", /* version= */ "",
|
||||
/* serial= */ "", /* numTuners= */ 0, /* numAudioSources= */ 0,
|
||||
/* isInitializationRequired= */ false, /* isCaptureSupported= */ false,
|
||||
/* bands= */ null, /* isBgScanSupported= */ false,
|
||||
/* supportedProgramTypes= */ new int[]{},
|
||||
/* supportedIdentifierTypes */ new int[]{},
|
||||
/* dabFrequencyTable= */ null, /* vendorInfo= */ null);
|
||||
AidlTestUtils.makeDefaultModuleProperties();
|
||||
|
||||
// Mocks
|
||||
@Mock
|
||||
@@ -108,7 +101,7 @@ public final class RadioModuleTest {
|
||||
|
||||
Bitmap imageTest = mRadioModule.getImage(imageId);
|
||||
|
||||
assertWithMessage("Image got from radio module").that(imageTest).isNull();
|
||||
assertWithMessage("Image from radio module").that(imageTest).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,10 +19,10 @@ 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.anyBoolean;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
@@ -93,13 +93,8 @@ public final class TunerSessionTest {
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
mRadioModule = new RadioModule(mBroadcastRadioMock, new RadioManager.ModuleProperties(
|
||||
/* id= */ 0, /* serviceName= */ "", /* classId= */ 0, /* implementor= */ "",
|
||||
/* product= */ "", /* version= */ "", /* serial= */ "", /* numTuners= */ 0,
|
||||
/* numAudioSources= */ 0, /* isInitializationRequired= */ false,
|
||||
/* isCaptureSupported= */ false, /* bands= */ null, /* isBgScanSupported= */ false,
|
||||
new int[] {}, new int[] {},
|
||||
/* dabFrequencyTable= */ null, /* vendorInfo= */ null), mLock);
|
||||
mRadioModule = new RadioModule(mBroadcastRadioMock,
|
||||
AidlTestUtils.makeDefaultModuleProperties(), mLock);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
mHalTunerCallback = (ITunerCallback) invocation.getArguments()[0];
|
||||
@@ -424,7 +419,7 @@ public final class TunerSessionTest {
|
||||
mTunerSessions[0].getImage(imageId);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for getting image with invalid ID")
|
||||
assertWithMessage("Get image exception")
|
||||
.that(thrown).hasMessageThat().contains("Image ID is missing");
|
||||
}
|
||||
|
||||
@@ -467,7 +462,7 @@ public final class TunerSessionTest {
|
||||
boolean isSupported = mTunerSessions[0].isConfigFlagSupported(flag);
|
||||
|
||||
verify(mBroadcastRadioMock).isConfigFlagSet(flag);
|
||||
assertWithMessage("Config flag %s is supported", flag).that(isSupported).isFalse();
|
||||
assertWithMessage("Config flag %s is supported", flag).that(isSupported).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.server.broadcastradio.hal2;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
|
||||
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.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.hardware.broadcastradio.V2_0.IBroadcastRadio;
|
||||
import android.hardware.radio.Announcement;
|
||||
import android.hardware.radio.IAnnouncementListener;
|
||||
import android.hardware.radio.ICloseHandle;
|
||||
import android.hardware.radio.ITuner;
|
||||
import android.hardware.radio.ITunerCallback;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.hardware.radio.RadioTuner;
|
||||
import android.hidl.manager.V1_0.IServiceManager;
|
||||
import android.hidl.manager.V1_0.IServiceNotification;
|
||||
import android.os.IBinder;
|
||||
import android.os.IHwBinder.DeathRecipient;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
|
||||
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class BroadcastRadioServiceHidlTest extends ExtendedRadioMockitoTestCase {
|
||||
|
||||
private static final int FM_RADIO_MODULE_ID = 0;
|
||||
private static final int DAB_RADIO_MODULE_ID = 1;
|
||||
private static final ArrayList<String> SERVICE_LIST =
|
||||
new ArrayList<>(Arrays.asList("FmService", "DabService"));
|
||||
private static final int[] TEST_ENABLED_TYPES = new int[]{Announcement.TYPE_TRAFFIC};
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
private BroadcastRadioService mBroadcastRadioService;
|
||||
private DeathRecipient mFmDeathRecipient;
|
||||
|
||||
@Mock
|
||||
private IServiceManager mServiceManagerMock;
|
||||
@Mock
|
||||
private RadioManager.ModuleProperties mFmModuleMock;
|
||||
@Mock
|
||||
private RadioManager.ModuleProperties mDabModuleMock;
|
||||
@Mock
|
||||
private RadioModule mFmRadioModuleMock;
|
||||
@Mock
|
||||
private RadioModule mDabRadioModuleMock;
|
||||
@Mock
|
||||
private IBroadcastRadio mFmHalServiceMock;
|
||||
@Mock
|
||||
private IBroadcastRadio mDabHalServiceMock;
|
||||
@Mock
|
||||
private TunerSession mFmTunerSessionMock;
|
||||
@Mock
|
||||
private ITunerCallback mTunerCallbackMock;
|
||||
@Mock
|
||||
private ICloseHandle mFmCloseHandleMock;
|
||||
@Mock
|
||||
private ICloseHandle mDabCloseHandleMock;
|
||||
@Mock
|
||||
private IAnnouncementListener mAnnouncementListenerMock;
|
||||
@Mock
|
||||
private IBinder mBinderMock;
|
||||
|
||||
@Override
|
||||
protected void initializeSession(StaticMockitoSessionBuilder builder) {
|
||||
builder.spyStatic(RadioModule.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listModules_withMultipleServiceNames() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
|
||||
assertWithMessage("Radio modules in HIDL broadcast radio HAL client")
|
||||
.that(mBroadcastRadioService.listModules())
|
||||
.containsExactly(mFmModuleMock, mDabModuleMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasModules_withIdFoundInModules() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
|
||||
assertWithMessage("DAB radio module in HIDL broadcast radio HAL client")
|
||||
.that(mBroadcastRadioService.hasModule(FM_RADIO_MODULE_ID)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasModules_withIdNotFoundInModules() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
|
||||
assertWithMessage("Radio module of id not found in HIDL broadcast radio HAL client")
|
||||
.that(mBroadcastRadioService.hasModule(DAB_RADIO_MODULE_ID + 1)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasAnyModules_withModulesExist() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
|
||||
assertWithMessage("Any radio module in HIDL broadcast radio HAL client")
|
||||
.that(mBroadcastRadioService.hasAnyModules()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openSession_withIdFound() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
|
||||
ITuner session = mBroadcastRadioService.openSession(FM_RADIO_MODULE_ID,
|
||||
/* legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock);
|
||||
|
||||
assertWithMessage("Session opened in FM radio module")
|
||||
.that(session).isEqualTo(mFmTunerSessionMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openSession_withIdNotFound() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
int moduleIdInvalid = DAB_RADIO_MODULE_ID + 1;
|
||||
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> {
|
||||
mBroadcastRadioService.openSession(moduleIdInvalid, /* legacyConfig= */ null,
|
||||
/* withAudio= */ true, mTunerCallbackMock);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for opening session with module id %s", moduleIdInvalid)
|
||||
.that(thrown).hasMessageThat().contains("Invalid module ID");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addAnnouncementListener_addsOnAllRadioModules() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
when(mAnnouncementListenerMock.asBinder()).thenReturn(mBinderMock);
|
||||
when(mFmRadioModuleMock.addAnnouncementListener(any(), any()))
|
||||
.thenReturn(mFmCloseHandleMock);
|
||||
when(mDabRadioModuleMock.addAnnouncementListener(any(), any()))
|
||||
.thenReturn(mDabCloseHandleMock);
|
||||
|
||||
mBroadcastRadioService.addAnnouncementListener(TEST_ENABLED_TYPES,
|
||||
mAnnouncementListenerMock);
|
||||
|
||||
verify(mFmRadioModuleMock).addAnnouncementListener(any(), any());
|
||||
verify(mDabRadioModuleMock).addAnnouncementListener(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void binderDied_forDeathRecipient() throws Exception {
|
||||
createBroadcastRadioService();
|
||||
|
||||
mFmDeathRecipient.serviceDied(FM_RADIO_MODULE_ID);
|
||||
|
||||
verify(mFmRadioModuleMock).closeSessions(eq(RadioTuner.ERROR_HARDWARE_FAILURE));
|
||||
assertWithMessage("FM radio module after FM broadcast radio HAL service died")
|
||||
.that(mBroadcastRadioService.hasModule(FM_RADIO_MODULE_ID)).isFalse();
|
||||
}
|
||||
|
||||
private void createBroadcastRadioService() throws RemoteException {
|
||||
mockServiceManager();
|
||||
mBroadcastRadioService = new BroadcastRadioService(/* nextModuleId= */ FM_RADIO_MODULE_ID,
|
||||
mLock, mServiceManagerMock);
|
||||
}
|
||||
|
||||
private void mockServiceManager() throws RemoteException {
|
||||
doAnswer(invocation -> {
|
||||
mFmDeathRecipient = (DeathRecipient) invocation.getArguments()[0];
|
||||
return null;
|
||||
}).when(mFmHalServiceMock).linkToDeath(any(), eq((long) FM_RADIO_MODULE_ID));
|
||||
|
||||
when(mServiceManagerMock.registerForNotifications(anyString(), anyString(),
|
||||
any(IServiceNotification.class))).thenAnswer(invocation -> {
|
||||
IServiceNotification serviceCallback =
|
||||
(IServiceNotification) invocation.getArguments()[2];
|
||||
for (int index = 0; index < SERVICE_LIST.size(); index++) {
|
||||
serviceCallback.onRegistration(IBroadcastRadio.kInterfaceName,
|
||||
SERVICE_LIST.get(index), /* b= */ false);
|
||||
}
|
||||
return true;
|
||||
}).thenReturn(true);
|
||||
|
||||
doReturn(mFmRadioModuleMock).when(() -> RadioModule.tryLoadingModule(
|
||||
eq(FM_RADIO_MODULE_ID), anyString(), any(Object.class)));
|
||||
doReturn(mDabRadioModuleMock).when(() -> RadioModule.tryLoadingModule(
|
||||
eq(DAB_RADIO_MODULE_ID), anyString(), any(Object.class)));
|
||||
|
||||
when(mFmRadioModuleMock.getProperties()).thenReturn(mFmModuleMock);
|
||||
when(mDabRadioModuleMock.getProperties()).thenReturn(mDabModuleMock);
|
||||
|
||||
when(mFmRadioModuleMock.getService()).thenReturn(mFmHalServiceMock);
|
||||
when(mDabRadioModuleMock.getService()).thenReturn(mDabHalServiceMock);
|
||||
|
||||
when(mFmRadioModuleMock.openSession(mTunerCallbackMock))
|
||||
.thenReturn(mFmTunerSessionMock);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.broadcastradio.hal2;
|
||||
|
||||
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.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.hardware.broadcastradio.V2_0.Constants;
|
||||
import android.hardware.broadcastradio.V2_0.IBroadcastRadio;
|
||||
import android.hardware.broadcastradio.V2_0.Result;
|
||||
import android.hardware.radio.Announcement;
|
||||
import android.hardware.radio.IAnnouncementListener;
|
||||
import android.hardware.radio.ICloseHandle;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Tests for HIDL HAL RadioModule.
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public final class RadioModuleHidlTest {
|
||||
|
||||
private static final int TEST_ENABLED_TYPE = Announcement.TYPE_EVENT;
|
||||
private static final RadioManager.ModuleProperties TEST_MODULE_PROPERTIES =
|
||||
TestUtils.makeDefaultModuleProperties();
|
||||
|
||||
@Mock
|
||||
private IBroadcastRadio mBroadcastRadioMock;
|
||||
@Mock
|
||||
private IAnnouncementListener mListenerMock;
|
||||
@Mock
|
||||
private android.hardware.broadcastradio.V2_0.ICloseHandle mHalCloseHandleMock;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private RadioModule mRadioModule;
|
||||
private android.hardware.broadcastradio.V2_0.IAnnouncementListener mHalListener;
|
||||
|
||||
@Before
|
||||
public void setup() throws RemoteException {
|
||||
mRadioModule = new RadioModule(mBroadcastRadioMock, TEST_MODULE_PROPERTIES, mLock);
|
||||
|
||||
when(mBroadcastRadioMock.getImage(anyInt())).thenReturn(new ArrayList<Byte>(0));
|
||||
|
||||
doAnswer(invocation -> {
|
||||
mHalListener = (android.hardware.broadcastradio.V2_0.IAnnouncementListener) invocation
|
||||
.getArguments()[1];
|
||||
IBroadcastRadio.registerAnnouncementListenerCallback cb =
|
||||
(IBroadcastRadio.registerAnnouncementListenerCallback)
|
||||
invocation.getArguments()[2];
|
||||
cb.onValues(Result.OK, mHalCloseHandleMock);
|
||||
return null;
|
||||
}).when(mBroadcastRadioMock).registerAnnouncementListener(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getService() {
|
||||
assertWithMessage("Service of radio module")
|
||||
.that(mRadioModule.getService()).isEqualTo(mBroadcastRadioMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getProperties() {
|
||||
assertWithMessage("Module properties of radio module")
|
||||
.that(mRadioModule.getProperties()).isEqualTo(TEST_MODULE_PROPERTIES);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getImage_withValidIdFromRadioModule() {
|
||||
int imageId = 1;
|
||||
|
||||
Bitmap imageTest = mRadioModule.getImage(imageId);
|
||||
|
||||
assertWithMessage("Image from radio module").that(imageTest).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getImage_withInvalidIdFromRadioModule_throwsIllegalArgumentException() {
|
||||
int invalidImageId = Constants.INVALID_IMAGE;
|
||||
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> {
|
||||
mRadioModule.getImage(invalidImageId);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for getting image with invalid ID")
|
||||
.that(thrown).hasMessageThat().contains("Image ID is missing");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addAnnouncementListener_listenerRegistered() throws Exception {
|
||||
ArrayList<Byte> enabledListExpected = new ArrayList<Byte>(Arrays.asList(
|
||||
(byte) TEST_ENABLED_TYPE));
|
||||
mRadioModule.addAnnouncementListener(new int[]{TEST_ENABLED_TYPE}, mListenerMock);
|
||||
|
||||
verify(mBroadcastRadioMock)
|
||||
.registerAnnouncementListener(eq(enabledListExpected), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onListUpdate_forAnnouncementListener() throws Exception {
|
||||
android.hardware.broadcastradio.V2_0.Announcement halAnnouncement =
|
||||
TestUtils.makeAnnouncement(TEST_ENABLED_TYPE, /* selectorFreq= */ 96300);
|
||||
mRadioModule.addAnnouncementListener(new int[]{TEST_ENABLED_TYPE}, mListenerMock);
|
||||
|
||||
mHalListener.onListUpdated(
|
||||
new ArrayList<android.hardware.broadcastradio.V2_0.Announcement>(
|
||||
Arrays.asList(halAnnouncement)));
|
||||
|
||||
verify(mListenerMock).onListUpdated(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void close_forCloseHandle() throws Exception {
|
||||
ICloseHandle closeHandle =
|
||||
mRadioModule.addAnnouncementListener(new int[]{TEST_ENABLED_TYPE}, mListenerMock);
|
||||
|
||||
closeHandle.close();
|
||||
|
||||
verify(mHalCloseHandleMock).close();
|
||||
}
|
||||
}
|
||||
@@ -95,9 +95,8 @@ public class StartProgramListUpdatesFanoutTest {
|
||||
public void setup() throws RemoteException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mRadioModule = new RadioModule(mBroadcastRadioMock, new RadioManager.ModuleProperties(0, "",
|
||||
0, "", "", "", "", 0, 0, false, false, null, false, new int[] {}, new int[] {},
|
||||
null, null), mLock);
|
||||
mRadioModule = new RadioModule(mBroadcastRadioMock,
|
||||
TestUtils.makeDefaultModuleProperties(), mLock);
|
||||
|
||||
doAnswer((Answer) invocation -> {
|
||||
mHalTunerCallback = (ITunerCallback) invocation.getArguments()[0];
|
||||
|
||||
@@ -33,6 +33,16 @@ final class TestUtils {
|
||||
throw new UnsupportedOperationException("TestUtils class is noninstantiable");
|
||||
}
|
||||
|
||||
static RadioManager.ModuleProperties makeDefaultModuleProperties() {
|
||||
return new RadioManager.ModuleProperties(
|
||||
/* id= */ 0, /* serviceName= */ "", /* classId= */ 0, /* implementor= */ "",
|
||||
/* product= */ "", /* version= */ "", /* serial= */ "", /* numTuners= */ 0,
|
||||
/* numAudioSources= */ 0, /* isInitializationRequired= */ false,
|
||||
/* isCaptureSupported= */ false, /* bands= */ null,
|
||||
/* isBgScanSupported= */ false, new int[] {}, new int[] {},
|
||||
/* dabFrequencyTable= */ null, /* vendorInfo= */ null);
|
||||
}
|
||||
|
||||
static RadioManager.ProgramInfo makeProgramInfo(ProgramSelector selector, int signalQuality) {
|
||||
return new RadioManager.ProgramInfo(selector,
|
||||
selector.getPrimaryId(), selector.getPrimaryId(), /* relatedContents= */ null,
|
||||
|
||||
@@ -37,12 +37,15 @@ import android.hardware.broadcastradio.V2_0.ITunerSession;
|
||||
import android.hardware.broadcastradio.V2_0.IdentifierType;
|
||||
import android.hardware.broadcastradio.V2_0.ProgramInfo;
|
||||
import android.hardware.broadcastradio.V2_0.Result;
|
||||
import android.hardware.broadcastradio.V2_0.VendorKeyValue;
|
||||
import android.hardware.radio.ProgramList;
|
||||
import android.hardware.radio.ProgramSelector;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.hardware.radio.RadioTuner;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -51,6 +54,8 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.mockito.verification.VerificationWithTimeout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Tests for HIDL HAL TunerSession.
|
||||
@@ -73,6 +78,7 @@ public final class TunerSessionHidlTest {
|
||||
private static final int UNSUPPORTED_CONFIG_FLAG = 0;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private final ArrayMap<Integer, Boolean> mHalConfigMap = new ArrayMap<>();
|
||||
private RadioModule mRadioModule;
|
||||
private ITunerCallback mHalTunerCallback;
|
||||
private ProgramInfo mHalCurrentInfo;
|
||||
@@ -84,13 +90,8 @@ public final class TunerSessionHidlTest {
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
mRadioModule = new RadioModule(mBroadcastRadioMock, new RadioManager.ModuleProperties(
|
||||
/* id= */ 0, /* serviceName= */ "", /* classId= */ 0, /* implementor= */ "",
|
||||
/* product= */ "", /* version= */ "", /* serial= */ "", /* numTuners= */ 0,
|
||||
/* numAudioSources= */ 0, /* isInitializationRequired= */ false,
|
||||
/* isCaptureSupported= */ false, /* bands= */ null, /* isBgScanSupported= */ false,
|
||||
new int[] {}, new int[] {},
|
||||
/* dabFrequencyTable= */ null, /* vendorInfo= */ null), mLock);
|
||||
mRadioModule = new RadioModule(mBroadcastRadioMock,
|
||||
TestUtils.makeDefaultModuleProperties(), mLock);
|
||||
|
||||
doAnswer(invocation -> {
|
||||
mHalTunerCallback = (ITunerCallback) invocation.getArguments()[0];
|
||||
@@ -142,6 +143,32 @@ public final class TunerSessionHidlTest {
|
||||
}).when(mHalTunerSessionMock).scan(anyBoolean(), anyBoolean());
|
||||
|
||||
when(mBroadcastRadioMock.getImage(anyInt())).thenReturn(new ArrayList<Byte>(0));
|
||||
|
||||
doAnswer(invocation -> {
|
||||
int configFlag = (int) invocation.getArguments()[0];
|
||||
ITunerSession.isConfigFlagSetCallback cb = (ITunerSession.isConfigFlagSetCallback)
|
||||
invocation.getArguments()[1];
|
||||
if (configFlag == UNSUPPORTED_CONFIG_FLAG) {
|
||||
cb.onValues(Result.NOT_SUPPORTED, false);
|
||||
return null;
|
||||
}
|
||||
cb.onValues(Result.OK, mHalConfigMap.getOrDefault(configFlag, false));
|
||||
return null;
|
||||
}).when(mHalTunerSessionMock).isConfigFlagSet(anyInt(), any());
|
||||
|
||||
doAnswer(invocation -> {
|
||||
int configFlag = (int) invocation.getArguments()[0];
|
||||
if (configFlag == UNSUPPORTED_CONFIG_FLAG) {
|
||||
return Result.NOT_SUPPORTED;
|
||||
}
|
||||
mHalConfigMap.put(configFlag, (boolean) invocation.getArguments()[1]);
|
||||
return Result.OK;
|
||||
}).when(mHalTunerSessionMock).setConfigFlag(anyInt(), anyBoolean());
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
mHalConfigMap.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -395,7 +422,7 @@ public final class TunerSessionHidlTest {
|
||||
mTunerSessions[0].getImage(imageId);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for getting image with invalid ID")
|
||||
assertWithMessage("Get image exception")
|
||||
.that(thrown).hasMessageThat().contains("Image ID is missing");
|
||||
}
|
||||
|
||||
@@ -430,6 +457,138 @@ public final class TunerSessionHidlTest {
|
||||
verify(mHalTunerSessionMock).stopProgramListUpdates();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSupported_withUnsupportedFlag_returnsFalse() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
int flag = UNSUPPORTED_CONFIG_FLAG;
|
||||
|
||||
boolean isSupported = mTunerSessions[0].isConfigFlagSupported(flag);
|
||||
|
||||
verify(mHalTunerSessionMock).isConfigFlagSet(eq(flag), any());
|
||||
assertWithMessage("Config flag %s is supported", flag).that(isSupported).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSupported_withSupportedFlag_returnsTrue() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
int flag = UNSUPPORTED_CONFIG_FLAG + 1;
|
||||
|
||||
boolean isSupported = mTunerSessions[0].isConfigFlagSupported(flag);
|
||||
|
||||
verify(mHalTunerSessionMock).isConfigFlagSet(eq(flag), any());
|
||||
assertWithMessage("Config flag %s is supported", flag).that(isSupported).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConfigFlag_withUnsupportedFlag_throwsRuntimeException() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
int flag = UNSUPPORTED_CONFIG_FLAG;
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
|
||||
mTunerSessions[0].setConfigFlag(flag, /* value= */ true);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for setting unsupported flag %s", flag)
|
||||
.that(thrown).hasMessageThat().contains("setConfigFlag: NOT_SUPPORTED");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConfigFlag_withFlagSetToTrue() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
int flag = UNSUPPORTED_CONFIG_FLAG + 1;
|
||||
|
||||
mTunerSessions[0].setConfigFlag(flag, /* value= */ true);
|
||||
|
||||
verify(mHalTunerSessionMock).setConfigFlag(flag, /* value= */ true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setConfigFlag_withFlagSetToFalse() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
int flag = UNSUPPORTED_CONFIG_FLAG + 1;
|
||||
|
||||
mTunerSessions[0].setConfigFlag(flag, /* value= */ false);
|
||||
|
||||
verify(mHalTunerSessionMock).setConfigFlag(flag, /* value= */ false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSet_withUnsupportedFlag_throwsRuntimeException()
|
||||
throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
int flag = UNSUPPORTED_CONFIG_FLAG;
|
||||
|
||||
RuntimeException thrown = assertThrows(RuntimeException.class, () -> {
|
||||
mTunerSessions[0].isConfigFlagSet(flag);
|
||||
});
|
||||
|
||||
assertWithMessage("Exception for check if unsupported flag %s is set", flag)
|
||||
.that(thrown).hasMessageThat().contains("isConfigFlagSet: NOT_SUPPORTED");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isConfigFlagSet_withSupportedFlag() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
int flag = UNSUPPORTED_CONFIG_FLAG + 1;
|
||||
boolean expectedConfigFlagValue = true;
|
||||
mTunerSessions[0].setConfigFlag(flag, /* value= */ expectedConfigFlagValue);
|
||||
|
||||
boolean isSet = mTunerSessions[0].isConfigFlagSet(flag);
|
||||
|
||||
assertWithMessage("Config flag %s is set", flag)
|
||||
.that(isSet).isEqualTo(expectedConfigFlagValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setParameters_withMockParameters() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
Map<String, String> parametersSet = Map.of("mockParam1", "mockValue1",
|
||||
"mockParam2", "mockValue2");
|
||||
|
||||
mTunerSessions[0].setParameters(parametersSet);
|
||||
|
||||
verify(mHalTunerSessionMock).setParameters(Convert.vendorInfoToHal(parametersSet));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getParameters_withMockKeys() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
ArrayList<String> parameterKeys = new ArrayList<>(Arrays.asList("mockKey1", "mockKey2"));
|
||||
|
||||
mTunerSessions[0].getParameters(parameterKeys);
|
||||
|
||||
verify(mHalTunerSessionMock).getParameters(parameterKeys);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onConfigFlagUpdated_forTunerCallback() throws Exception {
|
||||
int numSessions = 3;
|
||||
openAidlClients(numSessions);
|
||||
|
||||
mHalTunerCallback.onAntennaStateChange(/* connected= */ false);
|
||||
|
||||
for (int index = 0; index < numSessions; index++) {
|
||||
verify(mAidlTunerCallbackMocks[index], CALLBACK_TIMEOUT)
|
||||
.onAntennaState(/* connected= */ false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onParametersUpdated_forTunerCallback() throws Exception {
|
||||
int numSessions = 3;
|
||||
openAidlClients(numSessions);
|
||||
ArrayList<VendorKeyValue> parametersUpdates = new ArrayList<VendorKeyValue>(Arrays.asList(
|
||||
TestUtils.makeVendorKeyValue("com.vendor.parameter1", "value1")));
|
||||
Map<String, String> parametersExpected = Map.of("com.vendor.parameter1", "value1");
|
||||
|
||||
mHalTunerCallback.onParametersUpdated(parametersUpdates);
|
||||
|
||||
for (int index = 0; index < numSessions; index++) {
|
||||
verify(mAidlTunerCallbackMocks[index], CALLBACK_TIMEOUT)
|
||||
.onParametersUpdated(parametersExpected);
|
||||
}
|
||||
}
|
||||
|
||||
private void openAidlClients(int numClients) throws Exception {
|
||||
mAidlTunerCallbackMocks = new android.hardware.radio.ITunerCallback[numClients];
|
||||
mTunerSessions = new TunerSession[numClients];
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.util.IndentingPrintWriter;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -132,10 +133,22 @@ public class BroadcastRadioService {
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
BroadcastRadioService(int nextModuleId, Object lock, IServiceManager manager) {
|
||||
mNextModuleId = nextModuleId;
|
||||
mLock = lock;
|
||||
Objects.requireNonNull(manager, "Service manager cannot be null");
|
||||
try {
|
||||
manager.registerForNotifications(IBroadcastRadio.kInterfaceName, "", mServiceListener);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.e(TAG, "Failed to register for service notifications: ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public @NonNull Collection<RadioManager.ModuleProperties> listModules() {
|
||||
Slog.v(TAG, "List HIDL 2.0 modules");
|
||||
synchronized (mLock) {
|
||||
return mModules.values().stream().map(module -> module.mProperties)
|
||||
return mModules.values().stream().map(module -> module.getProperties())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -154,7 +167,7 @@ public class BroadcastRadioService {
|
||||
|
||||
public ITuner openSession(int moduleId, @Nullable RadioManager.BandConfig legacyConfig,
|
||||
boolean withAudio, @NonNull ITunerCallback callback) throws RemoteException {
|
||||
Slog.v(TAG, "Open HIDL 2.0 session");
|
||||
Slog.v(TAG, "Open HIDL 2.0 session with module id " + moduleId);
|
||||
Objects.requireNonNull(callback);
|
||||
|
||||
if (!withAudio) {
|
||||
|
||||
@@ -58,7 +58,7 @@ class RadioModule {
|
||||
private static final int RADIO_EVENT_LOGGER_QUEUE_SIZE = 25;
|
||||
|
||||
@NonNull private final IBroadcastRadio mService;
|
||||
@NonNull public final RadioManager.ModuleProperties mProperties;
|
||||
@NonNull private final RadioManager.ModuleProperties mProperties;
|
||||
|
||||
private final Object mLock;
|
||||
@NonNull private final Handler mHandler;
|
||||
@@ -177,6 +177,10 @@ class RadioModule {
|
||||
return mService;
|
||||
}
|
||||
|
||||
public RadioManager.ModuleProperties getProperties() {
|
||||
return mProperties;
|
||||
}
|
||||
|
||||
public @NonNull TunerSession openSession(@NonNull android.hardware.radio.ITunerCallback userCb)
|
||||
throws RemoteException {
|
||||
mEventLogger.logRadioEvent("Open TunerSession");
|
||||
|
||||
Reference in New Issue
Block a user