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

Commit f168a291 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk
Browse files

Move processing off of HIDL Binder

Bug: 138412770
Test: atest StartProgramListUpdatesFanoutTest
Change-Id: I51a89c5792a1938cfd6720a10b6830b8cf62b9cd
parent 099615b9
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -211,10 +211,12 @@ class TunerCallbackAdapter extends ITunerCallback.Stub {

    @Override
    public void onProgramListUpdated(ProgramList.Chunk chunk) {
        mHandler.post(() -> {
            synchronized (mLock) {
                if (mProgramList == null) return;
                mProgramList.apply(Objects.requireNonNull(chunk));
            }
        });
    }

    @Override
+10 −6
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -43,6 +44,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
import org.mockito.verification.VerificationWithTimeout;

import java.util.Arrays;
import java.util.HashSet;
@@ -56,6 +58,8 @@ import java.util.List;
public class StartProgramListUpdatesFanoutTest {
    private static final String TAG = "BroadcastRadioTests.hal2.StartProgramListUpdatesFanout";

    private static final VerificationWithTimeout CB_TIMEOUT = timeout(100);

    // Mocks
    @Mock IBroadcastRadio mBroadcastRadioMock;
    @Mock ITunerSession mHalTunerSessionMock;
@@ -200,10 +204,10 @@ public class StartProgramListUpdatesFanoutTest {

        // Adding mDabEnsembleInfo should not update any client.
        updateHalProgramInfo(false, Arrays.asList(mDabEnsembleInfo), null);
        verify(mAidlTunerCallbackMocks[0], times(1)).onProgramListUpdated(any());
        verify(mAidlTunerCallbackMocks[1], times(2)).onProgramListUpdated(any());
        verify(mAidlTunerCallbackMocks[2], times(1)).onProgramListUpdated(any());
        verify(mAidlTunerCallbackMocks[3], times(2)).onProgramListUpdated(any());
        verify(mAidlTunerCallbackMocks[0], CB_TIMEOUT.times(1)).onProgramListUpdated(any());
        verify(mAidlTunerCallbackMocks[1], CB_TIMEOUT.times(2)).onProgramListUpdated(any());
        verify(mAidlTunerCallbackMocks[2], CB_TIMEOUT.times(1)).onProgramListUpdated(any());
        verify(mAidlTunerCallbackMocks[3], CB_TIMEOUT.times(2)).onProgramListUpdated(any());
    }

    @Test
@@ -240,7 +244,7 @@ public class StartProgramListUpdatesFanoutTest {

        // Update the HAL with mModifiedAmFmInfo, and verify only the remaining client is updated.
        updateHalProgramInfo(true, Arrays.asList(mModifiedAmFmInfo), null);
        verify(mAidlTunerCallbackMocks[0], times(1)).onProgramListUpdated(any());
        verify(mAidlTunerCallbackMocks[0], CB_TIMEOUT.times(1)).onProgramListUpdated(any());
        verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], true,
                Arrays.asList(mModifiedAmFmInfo), null);

@@ -313,6 +317,6 @@ public class StartProgramListUpdatesFanoutTest {
        }
        ProgramList.Chunk expectedChunk = new ProgramList.Chunk(purge, true, modifiedSet,
                removedSet);
        verify(clientMock).onProgramListUpdated(expectedChunk);
        verify(clientMock, CB_TIMEOUT).onProgramListUpdated(expectedChunk);
    }
}
+32 −15
Original line number Diff line number Diff line
@@ -35,6 +35,8 @@ import android.hardware.broadcastradio.V2_0.Result;
import android.hardware.broadcastradio.V2_0.VendorKeyValue;
import android.hardware.radio.RadioManager;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.util.MutableInt;
import android.util.Slog;
@@ -45,6 +47,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -56,6 +59,7 @@ class RadioModule {
    @NonNull public final RadioManager.ModuleProperties mProperties;

    private final Object mLock = new Object();
    @NonNull private final Handler mHandler;

    @GuardedBy("mLock")
    private ITunerSession mHalTunerSession;
@@ -77,22 +81,24 @@ class RadioModule {
    private final ITunerCallback mHalTunerCallback = new ITunerCallback.Stub() {
        @Override
        public void onTuneFailed(int result, ProgramSelector programSelector) {
            fanoutAidlCallback(cb -> cb.onTuneFailed(result, Convert.programSelectorFromHal(
                    programSelector)));
            lockAndFireLater(() -> {
                android.hardware.radio.ProgramSelector csel =
                        Convert.programSelectorFromHal(programSelector);
                fanoutAidlCallbackLocked(cb -> cb.onTuneFailed(result, csel));
            });
        }

        @Override
        public void onCurrentProgramInfoChanged(ProgramInfo halProgramInfo) {
            RadioManager.ProgramInfo programInfo = Convert.programInfoFromHal(halProgramInfo);
            synchronized (mLock) {
                mCurrentProgramInfo = programInfo;
                fanoutAidlCallbackLocked(cb -> cb.onCurrentProgramInfoChanged(programInfo));
            }
            lockAndFireLater(() -> {
                mCurrentProgramInfo = Convert.programInfoFromHal(halProgramInfo);
                fanoutAidlCallbackLocked(cb -> cb.onCurrentProgramInfoChanged(mCurrentProgramInfo));
            });
        }

        @Override
        public void onProgramListUpdated(ProgramListChunk programListChunk) {
            synchronized (mLock) {
            lockAndFireLater(() -> {
                android.hardware.radio.ProgramList.Chunk chunk =
                        Convert.programListChunkFromHal(programListChunk);
                mProgramInfoCache.filterAndApplyChunk(chunk);
@@ -100,20 +106,23 @@ class RadioModule {
                for (TunerSession tunerSession : mAidlTunerSessions) {
                    tunerSession.onMergedProgramListUpdateFromHal(chunk);
                }
            }
            });
        }

        @Override
        public void onAntennaStateChange(boolean connected) {
            synchronized (mLock) {
            lockAndFireLater(() -> {
                mAntennaConnected = connected;
                fanoutAidlCallbackLocked(cb -> cb.onAntennaState(connected));
            }
            });
        }

        @Override
        public void onParametersUpdated(ArrayList<VendorKeyValue> parameters) {
            fanoutAidlCallback(cb -> cb.onParametersUpdated(Convert.vendorInfoFromHal(parameters)));
            lockAndFireLater(() -> {
                Map<String, String> cparam = Convert.vendorInfoFromHal(parameters);
                fanoutAidlCallbackLocked(cb -> cb.onParametersUpdated(cparam));
            });
        }
    };

@@ -126,6 +135,7 @@ class RadioModule {
            @NonNull RadioManager.ModuleProperties properties) {
        mProperties = Objects.requireNonNull(properties);
        mService = Objects.requireNonNull(service);
        mHandler = new Handler(Looper.getMainLooper());
    }

    public static @Nullable RadioModule tryLoadingModule(int idx, @NonNull String fqName) {
@@ -310,15 +320,22 @@ class RadioModule {
        }
    }

    // add to mHandler queue, but ensure the runnable holds mLock when it gets executed
    private void lockAndFireLater(Runnable r) {
        mHandler.post(() -> {
            synchronized (mLock) {
                r.run();
            }
        });
    }

    interface AidlCallbackRunnable {
        void run(android.hardware.radio.ITunerCallback callback) throws RemoteException;
    }

    // Invokes runnable with each TunerSession currently open.
    void fanoutAidlCallback(AidlCallbackRunnable runnable) {
        synchronized (mLock) {
            fanoutAidlCallbackLocked(runnable);
        }
        lockAndFireLater(() -> fanoutAidlCallbackLocked(runnable));
    }

    private void fanoutAidlCallbackLocked(AidlCallbackRunnable runnable) {