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

Commit c8b8b298 authored by Weilin Xu's avatar Weilin Xu
Browse files

Refactor locks in radio client for AIDL HAL

Seperate locks were used for radio service implementation, radio
module, and tuner session for broadcast radio AIDL HAL client to
minimize performance issue. Potential dead lock issue in
TunerSession#close was also fixed.

Bug: 258688572
Test: atest com.android.server.broadcastradio.aidl
Test: atest android.broadcastradio.cts
Change-Id: I8de3afa2935e077488e7575bb9b64495c2113292
parent 498e07e9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -210,9 +210,9 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
                any(IServiceCallback.class)));

        doReturn(mFmRadioModuleMock).when(() -> RadioModule.tryLoadingModule(
                eq(FM_RADIO_MODULE_ID), anyString(), any(IBinder.class), any(Object.class)));
                eq(FM_RADIO_MODULE_ID), anyString(), any(IBinder.class)));
        doReturn(mDabRadioModuleMock).when(() -> RadioModule.tryLoadingModule(
                eq(DAB_RADIO_MODULE_ID), anyString(), any(IBinder.class), any(Object.class)));
                eq(DAB_RADIO_MODULE_ID), anyString(), any(IBinder.class)));

        when(mFmRadioModuleMock.getProperties()).thenReturn(mFmModuleMock);
        when(mDabRadioModuleMock.getProperties()).thenReturn(mDabModuleMock);
+1 −2
Original line number Diff line number Diff line
@@ -58,14 +58,13 @@ public final class RadioModuleTest {
    @Mock
    private android.hardware.broadcastradio.ICloseHandle mHalCloseHandleMock;

    private final Object mLock = new Object();
    // RadioModule under test
    private RadioModule mRadioModule;
    private android.hardware.broadcastradio.IAnnouncementListener mHalListener;

    @Before
    public void setup() throws RemoteException {
        mRadioModule = new RadioModule(mBroadcastRadioMock, TEST_MODULE_PROPERTIES, mLock);
        mRadioModule = new RadioModule(mBroadcastRadioMock, TEST_MODULE_PROPERTIES);

        // TODO(b/241118988): test non-null image for getImage method
        when(mBroadcastRadioMock.getImage(anyInt())).thenReturn(null);
+1 −2
Original line number Diff line number Diff line
@@ -83,7 +83,6 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
    @Mock private IBroadcastRadio mBroadcastRadioMock;
    private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks;

    private final Object mLock = new Object();
    // RadioModule under test
    private RadioModule mRadioModule;

@@ -104,7 +103,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
        doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());

        mRadioModule = new RadioModule(mBroadcastRadioMock,
                AidlTestUtils.makeDefaultModuleProperties(), mLock);
                AidlTestUtils.makeDefaultModuleProperties());

        doAnswer(invocation -> {
            mHalTunerCallback = (ITunerCallback) invocation.getArguments()[0];
+1 −1
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ public final class BroadcastRadioServiceImpl {
                }

                RadioModule radioModule =
                        RadioModule.tryLoadingModule(moduleId, name, newBinder, mLock);
                        RadioModule.tryLoadingModule(moduleId, name, newBinder);
                if (radioModule == null) {
                    Slogf.w(TAG, "No module %s with id %d (HAL AIDL)", name, moduleId);
                    return;
+22 −31
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ final class RadioModule {

    private final IBroadcastRadio mService;

    private final Object mLock;
    private final Object mLock = new Object();
    private final Handler mHandler;
    private final RadioLogger mLogger;
    private final RadioManager.ModuleProperties mProperties;
@@ -165,18 +165,15 @@ final class RadioModule {
    };

    @VisibleForTesting
    RadioModule(IBroadcastRadio service,
            RadioManager.ModuleProperties properties, Object lock) {
    RadioModule(IBroadcastRadio service, RadioManager.ModuleProperties properties) {
        mProperties = Objects.requireNonNull(properties, "properties cannot be null");
        mService = Objects.requireNonNull(service, "service cannot be null");
        mLock = Objects.requireNonNull(lock, "lock cannot be null");
        mHandler = new Handler(Looper.getMainLooper());
        mLogger = new RadioLogger(TAG, RADIO_EVENT_LOGGER_QUEUE_SIZE);
    }

    @Nullable
    static RadioModule tryLoadingModule(int moduleId, String moduleName,
            IBinder serviceBinder, Object lock) {
    static RadioModule tryLoadingModule(int moduleId, String moduleName, IBinder serviceBinder) {
        try {
            Slogf.i(TAG, "Try loading module for module id = %d, module name = %s",
                    moduleId, moduleName);
@@ -206,7 +203,7 @@ final class RadioModule {
            RadioManager.ModuleProperties prop = ConversionUtils.propertiesFromHalProperties(
                    moduleId, moduleName, service.getProperties(), amfmConfig, dabConfig);

            return new RadioModule(service, prop, lock);
            return new RadioModule(service, prop);
        } catch (RemoteException ex) {
            Slogf.e(TAG, ex, "Failed to load module %s", moduleName);
            return null;
@@ -222,10 +219,8 @@ final class RadioModule {
    }

    void setInternalHalCallback() throws RemoteException {
        synchronized (mLock) {
        mService.setTunerCallback(mHalTunerCallback);
    }
    }

    TunerSession openSession(android.hardware.radio.ITunerCallback userCb)
            throws RemoteException {
@@ -234,7 +229,7 @@ final class RadioModule {
        Boolean antennaConnected;
        RadioManager.ProgramInfo currentProgramInfo;
        synchronized (mLock) {
            tunerSession = new TunerSession(this, mService, userCb, mLock);
            tunerSession = new TunerSession(this, mService, userCb);
            mAidlTunerSessions.add(tunerSession);
            antennaConnected = mAntennaConnected;
            currentProgramInfo = mCurrentProgramInfo;
@@ -356,6 +351,7 @@ final class RadioModule {
            // Otherwise, update the HAL's filter, and AIDL clients will be updated when
            // mHalTunerCallback.onProgramListUpdated() is called.
            mUnionOfAidlProgramFilters = newFilter;
        }
        try {
            mService.startProgramListUpdates(
                    ConversionUtils.filterToHalProgramFilter(newFilter));
@@ -365,7 +361,6 @@ final class RadioModule {
            Slogf.e(TAG, ex, "mHalTunerSession.startProgramListUpdates() failed");
        }
    }
    }

    void onTunerSessionClosed(TunerSession tunerSession) {
        synchronized (mLock) {
@@ -453,13 +448,11 @@ final class RadioModule {
            }
        };

        synchronized (mLock) {
        try {
            hwCloseHandle[0] = mService.registerAnnouncementListener(hwListener, enabledList);
        } catch (RuntimeException ex) {
            throw ConversionUtils.throwOnError(ex, /* action= */ "AnnouncementListener");
        }
        }

        return new android.hardware.radio.ICloseHandle.Stub() {
            public void close() {
@@ -478,13 +471,11 @@ final class RadioModule {
        if (id == 0) throw new IllegalArgumentException("Image ID is missing");

        byte[] rawImage;
        synchronized (mLock) {
        try {
            rawImage = mService.getImage(id);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        }

        if (rawImage == null || rawImage.length == 0) return null;

Loading