diff --git a/core/java/android/hardware/radio/IRadioService.aidl b/core/java/android/hardware/radio/IRadioService.aidl index c7131a7fe9c95..9349cf7d0c327 100644 --- a/core/java/android/hardware/radio/IRadioService.aidl +++ b/core/java/android/hardware/radio/IRadioService.aidl @@ -31,7 +31,7 @@ interface IRadioService { List 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); diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java index f072e3b43b4ad..8c6083ce49b63 100644 --- a/core/java/android/hardware/radio/RadioManager.java +++ b/core/java/android/hardware/radio/RadioManager.java @@ -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; } } diff --git a/core/tests/BroadcastRadioTests/AndroidManifest.xml b/core/tests/BroadcastRadioTests/AndroidManifest.xml index 8f655efe4f07d..fef3d16a183b9 100644 --- a/core/tests/BroadcastRadioTests/AndroidManifest.xml +++ b/core/tests/BroadcastRadioTests/AndroidManifest.xml @@ -18,6 +18,8 @@ package="com.android.frameworks.broadcastradiotests"> + + diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java index 75f8c954be5ec..7c3d2f2138a40 100644 --- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java +++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java @@ -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); diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java index ce3e019520c84..b9f4c3fa0a779 100644 --- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java +++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/RadioManagerTest.java @@ -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); diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java index 8b257e832e436..c7b82b1caca64 100644 --- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java +++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/TunerAdapterTest.java @@ -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]; diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/IRadioServiceAidlImplTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/IRadioServiceAidlImplTest.java index 16c1499a2775a..da51ba45174cc 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/IRadioServiceAidlImplTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/IRadioServiceAidlImplTest.java @@ -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"); diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/IRadioServiceHidlImplTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/IRadioServiceHidlImplTest.java index 164c9aff127a7..20bc8d404d760 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/IRadioServiceHidlImplTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/IRadioServiceHidlImplTest.java @@ -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"); diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java index 161ac2dc6aa03..3e9e9922431bb 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java @@ -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 diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java index 98103f6eddd39..22f3bd4abe113 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java @@ -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 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); } } diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java index 5d0e07613a98f..ba0579171c435 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java @@ -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); diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java index 464ecb2b50a11..78b5a4ad71de8 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java @@ -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]); } } diff --git a/services/core/java/com/android/server/broadcastradio/IRadioServiceAidlImpl.java b/services/core/java/com/android/server/broadcastradio/IRadioServiceAidlImpl.java index b66120d428c3f..6a010424db139 100644 --- a/services/core/java/com/android/server/broadcastradio/IRadioServiceAidlImpl.java +++ b/services/core/java/com/android/server/broadcastradio/IRadioServiceAidlImpl.java @@ -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 diff --git a/services/core/java/com/android/server/broadcastradio/IRadioServiceHidlImpl.java b/services/core/java/com/android/server/broadcastradio/IRadioServiceHidlImpl.java index 8a1ba19e24ab7..408fba1bff3b1 100644 --- a/services/core/java/com/android/server/broadcastradio/IRadioServiceHidlImpl.java +++ b/services/core/java/com/android/server/broadcastradio/IRadioServiceHidlImpl.java @@ -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); } diff --git a/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java b/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java index 772cd4144f11b..03acf72725e7d 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java @@ -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); } diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java index c0a238feb9b55..4f2bfd1c1e520 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java @@ -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 modified = new ArraySet<>(); Iterator modifiedIterator = chunk.getModified().iterator(); while (modifiedIterator.hasNext()) { RadioManager.ProgramInfo info = modifiedIterator.next(); - if (programInfoMeetsSdkVersionRequirement(info, targetSdkVersion)) { + if (programInfoMeetsSdkVersionRequirement(info, uid)) { modified.add(info); } } diff --git a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java index f8c19ae2b8f18..132fb8ef8a952 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java @@ -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 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"); diff --git a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java index fe8c23845d2ab..0a3823f038fa9 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java @@ -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));