Merge "Use CompatChanges to radio app version check" into udc-dev
This commit is contained in:
@@ -31,7 +31,7 @@ interface IRadioService {
|
||||
List<RadioManager.ModuleProperties> listModules();
|
||||
|
||||
ITuner openTuner(int moduleId, in RadioManager.BandConfig bandConfig, boolean withAudio,
|
||||
in ITunerCallback callback, int targetSdkVersion);
|
||||
in ITunerCallback callback);
|
||||
|
||||
ICloseHandle addAnnouncementListener(in int[] enabledTypes,
|
||||
in IAnnouncementListener listener);
|
||||
|
||||
@@ -1796,7 +1796,7 @@ public class RadioManager {
|
||||
ITuner tuner;
|
||||
TunerCallbackAdapter halCallback = new TunerCallbackAdapter(callback, handler);
|
||||
try {
|
||||
tuner = mService.openTuner(moduleId, config, withAudio, halCallback, mTargetSdkVersion);
|
||||
tuner = mService.openTuner(moduleId, config, withAudio, halCallback);
|
||||
} catch (RemoteException | IllegalArgumentException | IllegalStateException ex) {
|
||||
Log.e(TAG, "Failed to open tuner", ex);
|
||||
return null;
|
||||
@@ -1873,7 +1873,6 @@ public class RadioManager {
|
||||
|
||||
@NonNull private final Context mContext;
|
||||
@NonNull private final IRadioService mService;
|
||||
private final int mTargetSdkVersion;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
@@ -1890,6 +1889,5 @@ public class RadioManager {
|
||||
public RadioManager(Context context, IRadioService service) {
|
||||
mContext = context;
|
||||
mService = service;
|
||||
mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
package="com.android.frameworks.broadcastradiotests">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_BROADCAST_RADIO" />
|
||||
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE" />
|
||||
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
|
||||
|
||||
<application android:debuggable="true">
|
||||
<uses-library android:name="android.test.runner" />
|
||||
|
||||
@@ -580,7 +580,7 @@ public final class ProgramListTest {
|
||||
doAnswer(invocation -> {
|
||||
mTunerCallback = (ITunerCallback) invocation.getArguments()[3];
|
||||
return mTunerMock;
|
||||
}).when(mRadioServiceMock).openTuner(anyInt(), any(), anyBoolean(), any(), anyInt());
|
||||
}).when(mRadioServiceMock).openTuner(anyInt(), any(), anyBoolean(), any());
|
||||
|
||||
mRadioTuner = radioManager.openTuner(/* moduleId= */ 0, band,
|
||||
/* withAudio= */ true, mTunerCallbackMock, /* handler= */ null);
|
||||
|
||||
@@ -30,7 +30,6 @@ import static org.mockito.Mockito.when;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
import android.util.ArrayMap;
|
||||
@@ -50,8 +49,6 @@ import java.util.Set;
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public final class RadioManagerTest {
|
||||
|
||||
private static final int TEST_TARGET_SDK_VERSION = Build.VERSION_CODES.CUR_DEVELOPMENT;
|
||||
|
||||
private static final int REGION = RadioManager.REGION_ITU_2;
|
||||
private static final int FM_LOWER_LIMIT = 87500;
|
||||
private static final int FM_UPPER_LIMIT = 108000;
|
||||
@@ -1043,14 +1040,13 @@ public final class RadioManagerTest {
|
||||
mRadioManager.openTuner(moduleId, FM_BAND_CONFIG, withAudio, mCallbackMock,
|
||||
/* handler= */ null);
|
||||
|
||||
verify(mRadioServiceMock).openTuner(eq(moduleId), eq(FM_BAND_CONFIG), eq(withAudio), any(),
|
||||
anyInt());
|
||||
verify(mRadioServiceMock).openTuner(eq(moduleId), eq(FM_BAND_CONFIG), eq(withAudio), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openTuner_whenServiceDied_returnsNull() throws Exception {
|
||||
createRadioManager();
|
||||
when(mRadioServiceMock.openTuner(anyInt(), any(), anyBoolean(), any(), anyInt()))
|
||||
when(mRadioServiceMock.openTuner(anyInt(), any(), anyBoolean(), any()))
|
||||
.thenThrow(new RemoteException());
|
||||
|
||||
RadioTuner nullTuner = mRadioManager.openTuner(/* moduleId= */ 0, FM_BAND_CONFIG,
|
||||
@@ -1166,7 +1162,6 @@ public final class RadioManagerTest {
|
||||
}
|
||||
|
||||
private void createRadioManager() throws RemoteException {
|
||||
mApplicationInfo.targetSdkVersion = TEST_TARGET_SDK_VERSION;
|
||||
when(mContextMock.getApplicationInfo()).thenReturn(mApplicationInfo);
|
||||
when(mRadioServiceMock.listModules()).thenReturn(Arrays.asList(AMFM_PROPERTIES));
|
||||
when(mRadioServiceMock.addAnnouncementListener(any(), any())).thenReturn(mCloseHandleMock);
|
||||
|
||||
@@ -86,7 +86,7 @@ public final class TunerAdapterTest {
|
||||
doAnswer(invocation -> {
|
||||
mTunerCallback = (ITunerCallback) invocation.getArguments()[3];
|
||||
return mTunerMock;
|
||||
}).when(mRadioServiceMock).openTuner(anyInt(), any(), anyBoolean(), any(), anyInt());
|
||||
}).when(mRadioServiceMock).openTuner(anyInt(), any(), anyBoolean(), any());
|
||||
|
||||
doAnswer(invocation -> {
|
||||
ProgramSelector program = (ProgramSelector) invocation.getArguments()[0];
|
||||
|
||||
@@ -24,7 +24,6 @@ import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -35,7 +34,6 @@ import android.hardware.radio.ICloseHandle;
|
||||
import android.hardware.radio.ITuner;
|
||||
import android.hardware.radio.ITunerCallback;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.ServiceManager;
|
||||
|
||||
@@ -58,7 +56,6 @@ public final class IRadioServiceAidlImplTest extends ExtendedRadioMockitoTestCas
|
||||
"android.hardware.broadcastradio.IBroadcastRadio/amfm";
|
||||
private static final String DAB_SERVICE_NAME =
|
||||
"android.hardware.broadcastradio.IBroadcastRadio/dab";
|
||||
private static final int TARGET_SDK_VERSION = Build.VERSION_CODES.CUR_DEVELOPMENT;
|
||||
|
||||
private IRadioServiceAidlImpl mAidlImpl;
|
||||
|
||||
@@ -86,7 +83,7 @@ public final class IRadioServiceAidlImplTest extends ExtendedRadioMockitoTestCas
|
||||
doNothing().when(mServiceMock).enforcePolicyAccess();
|
||||
|
||||
when(mHalMock.listModules()).thenReturn(List.of(mModuleMock));
|
||||
when(mHalMock.openSession(anyInt(), any(), anyBoolean(), any(), eq(TARGET_SDK_VERSION)))
|
||||
when(mHalMock.openSession(anyInt(), any(), anyBoolean(), any()))
|
||||
.thenReturn(mTunerMock);
|
||||
when(mHalMock.addAnnouncementListener(any(), any())).thenReturn(mICloseHandle);
|
||||
|
||||
@@ -118,7 +115,7 @@ public final class IRadioServiceAidlImplTest extends ExtendedRadioMockitoTestCas
|
||||
@Test
|
||||
public void openTuner_forAidlImpl() throws Exception {
|
||||
ITuner tuner = mAidlImpl.openTuner(/* moduleId= */ 0, mBandConfigMock,
|
||||
/* withAudio= */ true, mTunerCallbackMock, TARGET_SDK_VERSION);
|
||||
/* withAudio= */ true, mTunerCallbackMock);
|
||||
|
||||
assertWithMessage("Tuner opened in AIDL HAL")
|
||||
.that(tuner).isEqualTo(mTunerMock);
|
||||
@@ -128,7 +125,7 @@ public final class IRadioServiceAidlImplTest extends ExtendedRadioMockitoTestCas
|
||||
public void openTuner_withNullCallbackForAidlImpl_fails() throws Exception {
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
|
||||
() -> mAidlImpl.openTuner(/* moduleId= */ 0, mBandConfigMock,
|
||||
/* withAudio= */ true, /* callback= */ null, TARGET_SDK_VERSION));
|
||||
/* withAudio= */ true, /* callback= */ null));
|
||||
|
||||
assertWithMessage("Exception for opening tuner with null callback")
|
||||
.that(thrown).hasMessageThat().contains("Callback must not be null");
|
||||
|
||||
@@ -33,7 +33,6 @@ import android.hardware.radio.ICloseHandle;
|
||||
import android.hardware.radio.ITuner;
|
||||
import android.hardware.radio.ITunerCallback;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.os.Build;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -51,7 +50,6 @@ public final class IRadioServiceHidlImplTest {
|
||||
|
||||
private static final int HAL1_MODULE_ID = 0;
|
||||
private static final int[] ENABLE_TYPES = new int[]{Announcement.TYPE_TRAFFIC};
|
||||
private static final int TARGET_SDK_VERSION = Build.VERSION_CODES.CUR_DEVELOPMENT;
|
||||
|
||||
private IRadioServiceHidlImpl mHidlImpl;
|
||||
|
||||
@@ -106,7 +104,7 @@ public final class IRadioServiceHidlImplTest {
|
||||
@Test
|
||||
public void openTuner_withHal1ModuleId_forHidlImpl() throws Exception {
|
||||
ITuner tuner = mHidlImpl.openTuner(HAL1_MODULE_ID, mBandConfigMock,
|
||||
/* withAudio= */ true, mTunerCallbackMock, TARGET_SDK_VERSION);
|
||||
/* withAudio= */ true, mTunerCallbackMock);
|
||||
|
||||
assertWithMessage("Tuner opened in HAL 1")
|
||||
.that(tuner).isEqualTo(mHal1TunerMock);
|
||||
@@ -115,7 +113,7 @@ public final class IRadioServiceHidlImplTest {
|
||||
@Test
|
||||
public void openTuner_withHal2ModuleId_forHidlImpl() throws Exception {
|
||||
ITuner tuner = mHidlImpl.openTuner(HAL1_MODULE_ID + 1, mBandConfigMock,
|
||||
/* withAudio= */ true, mTunerCallbackMock, TARGET_SDK_VERSION);
|
||||
/* withAudio= */ true, mTunerCallbackMock);
|
||||
|
||||
assertWithMessage("Tuner opened in HAL 2")
|
||||
.that(tuner).isEqualTo(mHal2TunerMock);
|
||||
@@ -125,7 +123,7 @@ public final class IRadioServiceHidlImplTest {
|
||||
public void openTuner_withNullCallbackForHidlImpl_fails() throws Exception {
|
||||
NullPointerException thrown = assertThrows(NullPointerException.class,
|
||||
() -> mHidlImpl.openTuner(/* moduleId= */ 0, mBandConfigMock,
|
||||
/* withAudio= */ true, /* callback= */ null, TARGET_SDK_VERSION));
|
||||
/* withAudio= */ true, /* callback= */ null));
|
||||
|
||||
assertWithMessage("Exception for opening tuner with null callback")
|
||||
.that(thrown).hasMessageThat().contains("Callback must not be null");
|
||||
|
||||
@@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.compat.CompatChanges;
|
||||
import android.os.Binder;
|
||||
import android.os.UserHandle;
|
||||
|
||||
@@ -46,8 +47,8 @@ public final class RadioServiceUserControllerTest extends ExtendedRadioMockitoTe
|
||||
|
||||
@Override
|
||||
protected void initializeSession(StaticMockitoSessionBuilder builder) {
|
||||
builder.spyStatic(ActivityManager.class)
|
||||
.spyStatic(Binder.class);
|
||||
builder.spyStatic(ActivityManager.class).spyStatic(Binder.class)
|
||||
.spyStatic(CompatChanges.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
||||
@@ -36,7 +36,6 @@ import android.hardware.radio.ITuner;
|
||||
import android.hardware.radio.ITunerCallback;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.hardware.radio.RadioTuner;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.IServiceCallback;
|
||||
import android.os.RemoteException;
|
||||
@@ -55,8 +54,6 @@ import java.util.Arrays;
|
||||
|
||||
public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTestCase {
|
||||
|
||||
private static final int TARGET_SDK_VERSION = Build.VERSION_CODES.CUR_DEVELOPMENT;
|
||||
|
||||
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 =
|
||||
@@ -140,8 +137,7 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
|
||||
createBroadcastRadioService();
|
||||
|
||||
ITuner session = mBroadcastRadioService.openSession(FM_RADIO_MODULE_ID,
|
||||
/* legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock,
|
||||
TARGET_SDK_VERSION);
|
||||
/* legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock);
|
||||
|
||||
assertWithMessage("Session opened in FM radio module")
|
||||
.that(session).isEqualTo(mFmTunerSessionMock);
|
||||
@@ -152,8 +148,7 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
|
||||
createBroadcastRadioService();
|
||||
|
||||
ITuner session = mBroadcastRadioService.openSession(DAB_RADIO_MODULE_ID + 1,
|
||||
/* legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock,
|
||||
TARGET_SDK_VERSION);
|
||||
/* legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock);
|
||||
|
||||
assertWithMessage("Session opened with id not found").that(session).isNull();
|
||||
}
|
||||
@@ -165,8 +160,7 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
|
||||
|
||||
IllegalStateException thrown = assertThrows(IllegalStateException.class,
|
||||
() -> mBroadcastRadioService.openSession(FM_RADIO_MODULE_ID,
|
||||
/* legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock,
|
||||
TARGET_SDK_VERSION));
|
||||
/* legacyConfig= */ null, /* withAudio= */ true, mTunerCallbackMock));
|
||||
|
||||
assertWithMessage("Exception for opening session by non-current user")
|
||||
.that(thrown).hasMessageThat().contains("Cannot open session for non-current user");
|
||||
@@ -178,8 +172,7 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
|
||||
|
||||
IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
|
||||
() -> mBroadcastRadioService.openSession(FM_RADIO_MODULE_ID,
|
||||
/* legacyConfig= */ null, /* withAudio= */ false, mTunerCallbackMock,
|
||||
TARGET_SDK_VERSION));
|
||||
/* legacyConfig= */ null, /* withAudio= */ false, mTunerCallbackMock));
|
||||
|
||||
assertWithMessage("Exception for opening session without audio")
|
||||
.that(thrown).hasMessageThat().contains("not supported");
|
||||
@@ -247,7 +240,6 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
|
||||
return null;
|
||||
}).when(mFmBinderMock).linkToDeath(any(), anyInt());
|
||||
|
||||
when(mFmRadioModuleMock.openSession(eq(mTunerCallbackMock), eq(TARGET_SDK_VERSION)))
|
||||
.thenReturn(mFmTunerSessionMock);
|
||||
when(mFmRadioModuleMock.openSession(mTunerCallbackMock)).thenReturn(mFmTunerSessionMock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.server.broadcastradio.aidl;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
|
||||
import android.app.compat.CompatChanges;
|
||||
import android.hardware.broadcastradio.AmFmBandRange;
|
||||
import android.hardware.broadcastradio.AmFmRegionConfig;
|
||||
import android.hardware.broadcastradio.DabTableEntry;
|
||||
@@ -29,17 +32,23 @@ import android.hardware.radio.Announcement;
|
||||
import android.hardware.radio.ProgramList;
|
||||
import android.hardware.radio.ProgramSelector;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.os.Build;
|
||||
|
||||
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
|
||||
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
|
||||
|
||||
import com.google.common.truth.Expect;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public final class ConversionUtilsTest {
|
||||
public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase {
|
||||
|
||||
private static final int U_APP_UID = 1001;
|
||||
private static final int T_APP_UID = 1002;
|
||||
|
||||
private static final int FM_LOWER_LIMIT = 87_500;
|
||||
private static final int FM_UPPER_LIMIT = 108_000;
|
||||
@@ -118,16 +127,29 @@ public final class ConversionUtilsTest {
|
||||
@Rule
|
||||
public final Expect expect = Expect.create();
|
||||
|
||||
@Override
|
||||
protected void initializeSession(StaticMockitoSessionBuilder builder) {
|
||||
builder.spyStatic(CompatChanges.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
doReturn(true).when(() -> CompatChanges.isChangeEnabled(
|
||||
ConversionUtils.RADIO_U_VERSION_REQUIRED, U_APP_UID));
|
||||
doReturn(false).when(() -> CompatChanges.isChangeEnabled(
|
||||
ConversionUtils.RADIO_U_VERSION_REQUIRED, T_APP_UID));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAtLeastU_withTSdkVersion_returnsFalse() {
|
||||
expect.withMessage("Target SDK version of T")
|
||||
.that(ConversionUtils.isAtLeastU(Build.VERSION_CODES.TIRAMISU)).isFalse();
|
||||
.that(ConversionUtils.isAtLeastU(T_APP_UID)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAtLeastU_withCurrentSdkVersion_returnsTrue() {
|
||||
expect.withMessage("Target SDK version of U")
|
||||
.that(ConversionUtils.isAtLeastU(Build.VERSION_CODES.CUR_DEVELOPMENT)).isTrue();
|
||||
.that(ConversionUtils.isAtLeastU(U_APP_UID)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -372,14 +394,14 @@ public final class ConversionUtilsTest {
|
||||
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();
|
||||
T_APP_UID)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void programSelectorMeetsSdkVersionRequirement_withRequiredVersionId_returnsTrue() {
|
||||
expect.withMessage("Selector %s with required SDK version", TEST_FM_SELECTOR)
|
||||
.that(ConversionUtils.programSelectorMeetsSdkVersionRequirement(TEST_FM_SELECTOR,
|
||||
Build.VERSION_CODES.TIRAMISU)).isTrue();
|
||||
T_APP_UID)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -389,7 +411,7 @@ public final class ConversionUtilsTest {
|
||||
|
||||
expect.withMessage("Program info %s without required SDK version", dabProgramInfo)
|
||||
.that(ConversionUtils.programInfoMeetsSdkVersionRequirement(dabProgramInfo,
|
||||
Build.VERSION_CODES.TIRAMISU)).isFalse();
|
||||
T_APP_UID)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -399,7 +421,7 @@ public final class ConversionUtilsTest {
|
||||
|
||||
expect.withMessage("Program info %s with required SDK version", fmProgramInfo)
|
||||
.that(ConversionUtils.programInfoMeetsSdkVersionRequirement(fmProgramInfo,
|
||||
Build.VERSION_CODES.TIRAMISU)).isTrue();
|
||||
T_APP_UID)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -413,7 +435,7 @@ public final class ConversionUtilsTest {
|
||||
Set.of(TEST_DAB_SID_EXT_ID, TEST_DAB_ENSEMBLE_ID, TEST_VENDOR_ID));
|
||||
|
||||
ProgramList.Chunk convertedChunk = ConversionUtils.convertChunkToTargetSdkVersion(chunk,
|
||||
Build.VERSION_CODES.TIRAMISU);
|
||||
T_APP_UID);
|
||||
|
||||
expect.withMessage(
|
||||
"Purged state of the converted program list chunk with lower SDK version")
|
||||
@@ -441,7 +463,7 @@ public final class ConversionUtilsTest {
|
||||
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);
|
||||
U_APP_UID);
|
||||
|
||||
expect.withMessage("Converted program list chunk with required SDK version")
|
||||
.that(convertedChunk).isEqualTo(chunk);
|
||||
|
||||
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.compat.CompatChanges;
|
||||
import android.graphics.Bitmap;
|
||||
import android.hardware.broadcastradio.IBroadcastRadio;
|
||||
import android.hardware.broadcastradio.ITunerCallback;
|
||||
@@ -46,7 +47,6 @@ import android.hardware.radio.ProgramList;
|
||||
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;
|
||||
@@ -73,7 +73,6 @@ import java.util.Set;
|
||||
*/
|
||||
public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
|
||||
private static final int TARGET_SDK_VERSION = Build.VERSION_CODES.CUR_DEVELOPMENT;
|
||||
private static final VerificationWithTimeout CALLBACK_TIMEOUT =
|
||||
timeout(/* millis= */ 200);
|
||||
private static final int SIGNAL_QUALITY = 90;
|
||||
@@ -125,11 +124,13 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
|
||||
@Override
|
||||
protected void initializeSession(StaticMockitoSessionBuilder builder) {
|
||||
builder.spyStatic(RadioServiceUserController.class);
|
||||
builder.spyStatic(RadioServiceUserController.class).spyStatic(CompatChanges.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
doReturn(true).when(() -> CompatChanges.isChangeEnabled(
|
||||
eq(ConversionUtils.RADIO_U_VERSION_REQUIRED), anyInt()));
|
||||
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
|
||||
|
||||
mRadioModule = new RadioModule(mBroadcastRadioMock,
|
||||
@@ -341,7 +342,9 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
|
||||
@Test
|
||||
public void tune_withLowerSdkVersion() throws Exception {
|
||||
openAidlClients(/* numClients= */ 1, Build.VERSION_CODES.TIRAMISU);
|
||||
doReturn(false).when(() -> CompatChanges.isChangeEnabled(
|
||||
eq(ConversionUtils.RADIO_U_VERSION_REQUIRED), anyInt()));
|
||||
openAidlClients(/* numClients= */ 1);
|
||||
ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
|
||||
RadioManager.ProgramInfo tuneInfo =
|
||||
AidlTestUtils.makeProgramInfo(initialSel, SIGNAL_QUALITY);
|
||||
@@ -1175,17 +1178,13 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
|
||||
.onParametersUpdated(parametersExpected);
|
||||
}
|
||||
}
|
||||
private void openAidlClients(int numClients) throws Exception {
|
||||
openAidlClients(numClients, TARGET_SDK_VERSION);
|
||||
}
|
||||
|
||||
private void openAidlClients(int numClients, int targetSdkVersion) throws Exception {
|
||||
private void openAidlClients(int numClients) throws Exception {
|
||||
mAidlTunerCallbackMocks = new android.hardware.radio.ITunerCallback[numClients];
|
||||
mTunerSessions = new TunerSession[numClients];
|
||||
for (int index = 0; index < numClients; index++) {
|
||||
mAidlTunerCallbackMocks[index] = mock(android.hardware.radio.ITunerCallback.class);
|
||||
mTunerSessions[index] = mRadioModule.openSession(mAidlTunerCallbackMocks[index],
|
||||
targetSdkVersion);
|
||||
mTunerSessions[index] = mRadioModule.openSession(mAidlTunerCallbackMocks[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,8 +86,7 @@ final class IRadioServiceAidlImpl extends IRadioService.Stub {
|
||||
|
||||
@Override
|
||||
public ITuner openTuner(int moduleId, RadioManager.BandConfig bandConfig,
|
||||
boolean withAudio, ITunerCallback callback, int targetSdkVersion)
|
||||
throws RemoteException {
|
||||
boolean withAudio, ITunerCallback callback) throws RemoteException {
|
||||
if (isDebugEnabled()) {
|
||||
Slogf.d(TAG, "Opening module %d", moduleId);
|
||||
}
|
||||
@@ -95,7 +94,7 @@ final class IRadioServiceAidlImpl extends IRadioService.Stub {
|
||||
if (callback == null) {
|
||||
throw new IllegalArgumentException("Callback must not be null");
|
||||
}
|
||||
return mHalAidl.openSession(moduleId, bandConfig, withAudio, callback, targetSdkVersion);
|
||||
return mHalAidl.openSession(moduleId, bandConfig, withAudio, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -92,8 +92,7 @@ final class IRadioServiceHidlImpl extends IRadioService.Stub {
|
||||
|
||||
@Override
|
||||
public ITuner openTuner(int moduleId, RadioManager.BandConfig bandConfig,
|
||||
boolean withAudio, ITunerCallback callback, int targetSdkVersion)
|
||||
throws RemoteException {
|
||||
boolean withAudio, ITunerCallback callback) throws RemoteException {
|
||||
if (isDebugEnabled()) {
|
||||
Slog.d(TAG, "Opening module " + moduleId);
|
||||
}
|
||||
|
||||
@@ -199,8 +199,7 @@ public final class BroadcastRadioServiceImpl {
|
||||
*/
|
||||
@Nullable
|
||||
public ITuner openSession(int moduleId, @Nullable RadioManager.BandConfig legacyConfig,
|
||||
boolean withAudio, ITunerCallback callback, int targetSdkVersion)
|
||||
throws RemoteException {
|
||||
boolean withAudio, ITunerCallback callback) throws RemoteException {
|
||||
if (DEBUG) {
|
||||
Slogf.d(TAG, "Open AIDL radio session");
|
||||
}
|
||||
@@ -223,7 +222,7 @@ public final class BroadcastRadioServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
TunerSession tunerSession = radioModule.openSession(callback, targetSdkVersion);
|
||||
TunerSession tunerSession = radioModule.openSession(callback);
|
||||
if (legacyConfig != null) {
|
||||
tunerSession.setConfiguration(legacyConfig);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
package com.android.server.broadcastradio.aidl;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.compat.CompatChanges;
|
||||
import android.compat.annotation.ChangeId;
|
||||
import android.compat.annotation.EnabledSince;
|
||||
import android.hardware.broadcastradio.AmFmRegionConfig;
|
||||
import android.hardware.broadcastradio.Announcement;
|
||||
import android.hardware.broadcastradio.DabTableEntry;
|
||||
@@ -57,16 +61,24 @@ import java.util.Set;
|
||||
* {@link android.hardware.radio}
|
||||
*/
|
||||
final class ConversionUtils {
|
||||
// TODO(b/241118988): Add unit test for ConversionUtils class
|
||||
private static final String TAG = "BcRadioAidlSrv.convert";
|
||||
|
||||
/**
|
||||
* With RADIO_U_VERSION_REQUIRED enabled, 44-bit DAB identifier
|
||||
* {@link IdentifierType#DAB_SID_EXT} from broadcast radio HAL can be passed as
|
||||
* {@link ProgramSelector#IDENTIFIER_TYPE_DAB_DMB_SID_EXT} to {@link RadioTuner}.
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
public static final long RADIO_U_VERSION_REQUIRED = 261770108L;
|
||||
|
||||
private ConversionUtils() {
|
||||
throw new UnsupportedOperationException("ConversionUtils class is noninstantiable");
|
||||
}
|
||||
|
||||
static boolean isAtLeastU(int targetSdkVersion) {
|
||||
// TODO(b/261770108): Use version code for U.
|
||||
return targetSdkVersion >= Build.VERSION_CODES.CUR_DEVELOPMENT;
|
||||
@SuppressLint("AndroidFrameworkRequiresPermission")
|
||||
static boolean isAtLeastU(int uid) {
|
||||
return CompatChanges.isChangeEnabled(RADIO_U_VERSION_REQUIRED, uid);
|
||||
}
|
||||
|
||||
static RuntimeException throwOnError(RuntimeException halException, String action) {
|
||||
@@ -584,9 +596,8 @@ final class ConversionUtils {
|
||||
return id.getType() == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT;
|
||||
}
|
||||
|
||||
static boolean programSelectorMeetsSdkVersionRequirement(ProgramSelector sel,
|
||||
int targetSdkVersion) {
|
||||
if (isAtLeastU(targetSdkVersion)) {
|
||||
static boolean programSelectorMeetsSdkVersionRequirement(ProgramSelector sel, int uid) {
|
||||
if (isAtLeastU(uid)) {
|
||||
return true;
|
||||
}
|
||||
if (sel.getPrimaryId().getType() == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT) {
|
||||
@@ -601,12 +612,11 @@ final class ConversionUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean programInfoMeetsSdkVersionRequirement(RadioManager.ProgramInfo info,
|
||||
int targetSdkVersion) {
|
||||
if (isAtLeastU(targetSdkVersion)) {
|
||||
static boolean programInfoMeetsSdkVersionRequirement(RadioManager.ProgramInfo info, int uid) {
|
||||
if (isAtLeastU(uid)) {
|
||||
return true;
|
||||
}
|
||||
if (!programSelectorMeetsSdkVersionRequirement(info.getSelector(), targetSdkVersion)) {
|
||||
if (!programSelectorMeetsSdkVersionRequirement(info.getSelector(), uid)) {
|
||||
return false;
|
||||
}
|
||||
if (isNewIdentifierInU(info.getLogicallyTunedTo())
|
||||
@@ -622,16 +632,15 @@ final class ConversionUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
static ProgramList.Chunk convertChunkToTargetSdkVersion(ProgramList.Chunk chunk,
|
||||
int targetSdkVersion) {
|
||||
if (isAtLeastU(targetSdkVersion)) {
|
||||
static ProgramList.Chunk convertChunkToTargetSdkVersion(ProgramList.Chunk chunk, int uid) {
|
||||
if (isAtLeastU(uid)) {
|
||||
return chunk;
|
||||
}
|
||||
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)) {
|
||||
if (programInfoMeetsSdkVersionRequirement(info, uid)) {
|
||||
modified.add(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,9 +101,9 @@ final class RadioModule {
|
||||
ConversionUtils.programSelectorFromHalProgramSelector(programSelector);
|
||||
int tunerResult = ConversionUtils.halResultToTunerResult(result);
|
||||
synchronized (mLock) {
|
||||
fanoutAidlCallbackLocked((cb, sdkVersion) -> {
|
||||
fanoutAidlCallbackLocked((cb, uid) -> {
|
||||
if (csel != null && !ConversionUtils
|
||||
.programSelectorMeetsSdkVersionRequirement(csel, sdkVersion)) {
|
||||
.programSelectorMeetsSdkVersionRequirement(csel, uid)) {
|
||||
Slogf.e(TAG, "onTuneFailed: cannot send program selector "
|
||||
+ "requiring higher target SDK version");
|
||||
return;
|
||||
@@ -123,9 +123,9 @@ final class RadioModule {
|
||||
"Program info from AIDL HAL is invalid");
|
||||
synchronized (mLock) {
|
||||
mCurrentProgramInfo = currentProgramInfo;
|
||||
fanoutAidlCallbackLocked((cb, sdkVersion) -> {
|
||||
fanoutAidlCallbackLocked((cb, uid) -> {
|
||||
if (!ConversionUtils.programInfoMeetsSdkVersionRequirement(
|
||||
currentProgramInfo, sdkVersion)) {
|
||||
currentProgramInfo, uid)) {
|
||||
Slogf.e(TAG, "onCurrentProgramInfoChanged: cannot send "
|
||||
+ "program info requiring higher target SDK version");
|
||||
return;
|
||||
@@ -156,7 +156,7 @@ final class RadioModule {
|
||||
fireLater(() -> {
|
||||
synchronized (mLock) {
|
||||
mAntennaConnected = connected;
|
||||
fanoutAidlCallbackLocked((cb, sdkVersion) -> cb.onAntennaState(connected));
|
||||
fanoutAidlCallbackLocked((cb, uid) -> cb.onAntennaState(connected));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -165,7 +165,7 @@ final class RadioModule {
|
||||
public void onConfigFlagUpdated(int flag, boolean value) {
|
||||
fireLater(() -> {
|
||||
synchronized (mLock) {
|
||||
fanoutAidlCallbackLocked((cb, sdkVersion) -> {
|
||||
fanoutAidlCallbackLocked((cb, uid) -> {
|
||||
cb.onConfigFlagUpdated(flag, value);
|
||||
});
|
||||
}
|
||||
@@ -178,7 +178,7 @@ final class RadioModule {
|
||||
synchronized (mLock) {
|
||||
Map<String, String> cparam =
|
||||
ConversionUtils.vendorInfoFromHalVendorKeyValues(parameters);
|
||||
fanoutAidlCallbackLocked((cb, sdkVersion) -> {
|
||||
fanoutAidlCallbackLocked((cb, uid) -> {
|
||||
cb.onParametersUpdated(cparam);
|
||||
});
|
||||
}
|
||||
@@ -244,14 +244,14 @@ final class RadioModule {
|
||||
mService.setTunerCallback(mHalTunerCallback);
|
||||
}
|
||||
|
||||
TunerSession openSession(android.hardware.radio.ITunerCallback userCb, int targetSdkVersion)
|
||||
TunerSession openSession(android.hardware.radio.ITunerCallback userCb)
|
||||
throws RemoteException {
|
||||
mLogger.logRadioEvent("Open TunerSession");
|
||||
TunerSession tunerSession;
|
||||
Boolean antennaConnected;
|
||||
RadioManager.ProgramInfo currentProgramInfo;
|
||||
synchronized (mLock) {
|
||||
tunerSession = new TunerSession(this, mService, userCb, targetSdkVersion);
|
||||
tunerSession = new TunerSession(this, mService, userCb);
|
||||
mAidlTunerSessions.add(tunerSession);
|
||||
antennaConnected = mAntennaConnected;
|
||||
currentProgramInfo = mCurrentProgramInfo;
|
||||
@@ -404,7 +404,7 @@ final class RadioModule {
|
||||
}
|
||||
|
||||
interface AidlCallbackRunnable {
|
||||
void run(android.hardware.radio.ITunerCallback callback, int targetSdkVersion)
|
||||
void run(android.hardware.radio.ITunerCallback callback, int uid)
|
||||
throws RemoteException;
|
||||
}
|
||||
|
||||
@@ -423,7 +423,7 @@ final class RadioModule {
|
||||
for (int i = 0; i < mAidlTunerSessions.size(); i++) {
|
||||
try {
|
||||
runnable.run(mAidlTunerSessions.valueAt(i).mCallback,
|
||||
mAidlTunerSessions.valueAt(i).getTargetSdkVersion());
|
||||
mAidlTunerSessions.valueAt(i).getUid());
|
||||
} catch (DeadObjectException ex) {
|
||||
// The other side died without calling close(), so just purge it from our records.
|
||||
Slogf.e(TAG, "Removing dead TunerSession");
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.hardware.radio.ITuner;
|
||||
import android.hardware.radio.ProgramList;
|
||||
import android.hardware.radio.ProgramSelector;
|
||||
import android.hardware.radio.RadioManager;
|
||||
import android.os.Binder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
@@ -46,7 +47,7 @@ final class TunerSession extends ITuner.Stub {
|
||||
private final RadioLogger mLogger;
|
||||
private final RadioModule mModule;
|
||||
final android.hardware.radio.ITunerCallback mCallback;
|
||||
private final int mTargetSdkVersion;
|
||||
private final int mUid;
|
||||
private final IBroadcastRadio mService;
|
||||
|
||||
@GuardedBy("mLock")
|
||||
@@ -61,11 +62,11 @@ final class TunerSession extends ITuner.Stub {
|
||||
private RadioManager.BandConfig mPlaceHolderConfig;
|
||||
|
||||
TunerSession(RadioModule radioModule, IBroadcastRadio service,
|
||||
android.hardware.radio.ITunerCallback callback, int targetSdkVersion) {
|
||||
android.hardware.radio.ITunerCallback callback) {
|
||||
mModule = Objects.requireNonNull(radioModule, "radioModule cannot be null");
|
||||
mService = Objects.requireNonNull(service, "service cannot be null");
|
||||
mCallback = Objects.requireNonNull(callback, "callback cannot be null");
|
||||
mTargetSdkVersion = targetSdkVersion;
|
||||
mUid = Binder.getCallingUid();
|
||||
mLogger = new RadioLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
@@ -130,7 +131,7 @@ final class TunerSession extends ITuner.Stub {
|
||||
mPlaceHolderConfig = Objects.requireNonNull(config, "config cannot be null");
|
||||
}
|
||||
Slogf.i(TAG, "Ignoring setConfiguration - not applicable for broadcastradio HAL AIDL");
|
||||
mModule.fanoutAidlCallback((cb, sdkVersion) -> cb.onConfigurationChanged(config));
|
||||
mModule.fanoutAidlCallback((cb, mUid) -> cb.onConfigurationChanged(config));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -254,7 +255,7 @@ final class TunerSession extends ITuner.Stub {
|
||||
Slogf.w(TAG, "Cannot start background scan on AIDL HAL client from non-current user");
|
||||
return false;
|
||||
}
|
||||
mModule.fanoutAidlCallback((cb, sdkVersion) -> {
|
||||
mModule.fanoutAidlCallback((cb, mUid) -> {
|
||||
cb.onBackgroundScanComplete();
|
||||
});
|
||||
return true;
|
||||
@@ -284,8 +285,8 @@ final class TunerSession extends ITuner.Stub {
|
||||
mModule.onTunerSessionProgramListFilterChanged(this);
|
||||
}
|
||||
|
||||
int getTargetSdkVersion() {
|
||||
return mTargetSdkVersion;
|
||||
int getUid() {
|
||||
return mUid;
|
||||
}
|
||||
|
||||
ProgramList.Filter getProgramListFilter() {
|
||||
@@ -323,10 +324,9 @@ final class TunerSession extends ITuner.Stub {
|
||||
}
|
||||
for (int i = 0; i < chunks.size(); i++) {
|
||||
try {
|
||||
if (!ConversionUtils.isAtLeastU(getTargetSdkVersion())) {
|
||||
if (!ConversionUtils.isAtLeastU(getUid())) {
|
||||
ProgramList.Chunk downgradedChunk =
|
||||
ConversionUtils.convertChunkToTargetSdkVersion(chunks.get(i),
|
||||
getTargetSdkVersion());
|
||||
ConversionUtils.convertChunkToTargetSdkVersion(chunks.get(i), getUid());
|
||||
mCallback.onProgramListUpdated(downgradedChunk);
|
||||
} else {
|
||||
mCallback.onProgramListUpdated(chunks.get(i));
|
||||
|
||||
Reference in New Issue
Block a user