Merge changes I63b1ee6b,I8de3afa2

* changes:
  Refactor locks in radio client for HIDL HAL
  Refactor locks in radio client for AIDL HAL
This commit is contained in:
TreeHugger Robot
2022-12-02 01:23:22 +00:00
committed by Android (Google) Code Review
15 changed files with 147 additions and 148 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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];

View File

@@ -59,8 +59,6 @@ public final class BroadcastRadioServiceHidlTest extends ExtendedRadioMockitoTes
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;
@@ -200,7 +198,7 @@ public final class BroadcastRadioServiceHidlTest extends ExtendedRadioMockitoTes
mockServiceManager();
mBroadcastRadioService = new BroadcastRadioService(/* nextModuleId= */ FM_RADIO_MODULE_ID,
mLock, mServiceManagerMock);
mServiceManagerMock);
}
private void mockServiceManager() throws RemoteException {
@@ -221,9 +219,9 @@ public final class BroadcastRadioServiceHidlTest extends ExtendedRadioMockitoTes
}).thenReturn(true);
doReturn(mFmRadioModuleMock).when(() -> RadioModule.tryLoadingModule(
eq(FM_RADIO_MODULE_ID), anyString(), any(Object.class)));
eq(FM_RADIO_MODULE_ID), anyString()));
doReturn(mDabRadioModuleMock).when(() -> RadioModule.tryLoadingModule(
eq(DAB_RADIO_MODULE_ID), anyString(), any(Object.class)));
eq(DAB_RADIO_MODULE_ID), anyString()));
when(mFmRadioModuleMock.getProperties()).thenReturn(mFmModuleMock);
when(mDabRadioModuleMock.getProperties()).thenReturn(mDabModuleMock);

View File

@@ -62,13 +62,12 @@ public final class RadioModuleHidlTest {
@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);
mRadioModule = new RadioModule(mBroadcastRadioMock, TEST_MODULE_PROPERTIES);
when(mBroadcastRadioMock.getImage(anyInt())).thenReturn(new ArrayList<Byte>(0));

View File

@@ -64,7 +64,6 @@ public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestC
@Mock ITunerSession mHalTunerSessionMock;
private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks;
private final Object mLock = new Object();
// RadioModule under test
private RadioModule mRadioModule;
@@ -100,7 +99,7 @@ public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestC
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
mRadioModule = new RadioModule(mBroadcastRadioMock,
TestUtils.makeDefaultModuleProperties(), mLock);
TestUtils.makeDefaultModuleProperties());
doAnswer((Answer) invocation -> {
mHalTunerCallback = (ITunerCallback) invocation.getArguments()[0];

View File

@@ -84,7 +84,6 @@ public final class TunerSessionHidlTest extends ExtendedRadioMockitoTestCase {
new RadioManager.FmBandConfig(FM_BAND_DESCRIPTOR);
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;
@@ -105,7 +104,7 @@ public final class TunerSessionHidlTest extends ExtendedRadioMockitoTestCase {
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
mRadioModule = new RadioModule(mBroadcastRadioMock,
TestUtils.makeDefaultModuleProperties(), mLock);
TestUtils.makeDefaultModuleProperties());
doAnswer(invocation -> {
mHalTunerCallback = (ITunerCallback) invocation.getArguments()[0];

View File

@@ -27,6 +27,7 @@ import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.broadcastradio.hal2.AnnouncementAggregator;
@@ -51,15 +52,17 @@ final class IRadioServiceHidlImpl extends IRadioService.Stub {
private final Object mLock = new Object();
private final BroadcastRadioService mService;
@GuardedBy("mLock")
private final List<RadioManager.ModuleProperties> mV1Modules;
IRadioServiceHidlImpl(BroadcastRadioService service) {
mService = Objects.requireNonNull(service, "broadcast radio service cannot be null");
mHal1 = new com.android.server.broadcastradio.hal1.BroadcastRadioService(mLock);
mHal1 = new com.android.server.broadcastradio.hal1.BroadcastRadioService();
mV1Modules = mHal1.loadModules();
OptionalInt max = mV1Modules.stream().mapToInt(RadioManager.ModuleProperties::getId).max();
mHal2 = new com.android.server.broadcastradio.hal2.BroadcastRadioService(
max.isPresent() ? max.getAsInt() + 1 : 0, mLock);
max.isPresent() ? max.getAsInt() + 1 : 0);
}
@VisibleForTesting
@@ -78,9 +81,11 @@ final class IRadioServiceHidlImpl extends IRadioService.Stub {
public List<RadioManager.ModuleProperties> listModules() {
mService.enforcePolicyAccess();
Collection<RadioManager.ModuleProperties> v2Modules = mHal2.listModules();
List<RadioManager.ModuleProperties> modules = new ArrayList<>(
mV1Modules.size() + v2Modules.size());
modules.addAll(mV1Modules);
List<RadioManager.ModuleProperties> modules;
synchronized (mLock) {
modules = new ArrayList<>(mV1Modules.size() + v2Modules.size());
modules.addAll(mV1Modules);
}
modules.addAll(v2Modules);
return modules;
}
@@ -131,7 +136,9 @@ final class IRadioServiceHidlImpl extends IRadioService.Stub {
radioPw.printf("HAL1: %s\n", mHal1);
radioPw.increaseIndent();
radioPw.printf("Modules of HAL1: %s\n", mV1Modules);
synchronized (mLock) {
radioPw.printf("Modules of HAL1: %s\n", mV1Modules);
}
radioPw.decreaseIndent();
radioPw.printf("HAL2:\n");

View File

@@ -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;

View File

@@ -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,9 +219,7 @@ final class RadioModule {
}
void setInternalHalCallback() throws RemoteException {
synchronized (mLock) {
mService.setTunerCallback(mHalTunerCallback);
}
mService.setTunerCallback(mHalTunerCallback);
}
TunerSession openSession(android.hardware.radio.ITunerCallback userCb)
@@ -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,14 +351,14 @@ 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));
} catch (RuntimeException ex) {
throw ConversionUtils.throwOnError(ex, /* action= */ "Start Program ListUpdates");
} catch (RemoteException ex) {
Slogf.e(TAG, ex, "mHalTunerSession.startProgramListUpdates() failed");
}
}
try {
mService.startProgramListUpdates(
ConversionUtils.filterToHalProgramFilter(newFilter));
} catch (RuntimeException ex) {
throw ConversionUtils.throwOnError(ex, /* action= */ "Start Program ListUpdates");
} catch (RemoteException ex) {
Slogf.e(TAG, ex, "mHalTunerSession.startProgramListUpdates() failed");
}
}
@@ -453,12 +448,10 @@ final class RadioModule {
}
};
synchronized (mLock) {
try {
hwCloseHandle[0] = mService.registerAnnouncementListener(hwListener, enabledList);
} catch (RuntimeException ex) {
throw ConversionUtils.throwOnError(ex, /* action= */ "AnnouncementListener");
}
try {
hwCloseHandle[0] = mService.registerAnnouncementListener(hwListener, enabledList);
} catch (RuntimeException ex) {
throw ConversionUtils.throwOnError(ex, /* action= */ "AnnouncementListener");
}
return new android.hardware.radio.ICloseHandle.Stub() {
@@ -478,12 +471,10 @@ 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();
}
try {
rawImage = mService.getImage(id);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
if (rawImage == null || rawImage.length == 0) return null;

View File

@@ -42,7 +42,7 @@ final class TunerSession extends ITuner.Stub {
private static final String TAG = "BcRadioAidlSrv.session";
private static final int TUNER_EVENT_LOGGER_QUEUE_SIZE = 25;
private final Object mLock;
private final Object mLock = new Object();
private final RadioLogger mLogger;
private final RadioModule mModule;
@@ -61,12 +61,10 @@ final class TunerSession extends ITuner.Stub {
private RadioManager.BandConfig mPlaceHolderConfig;
TunerSession(RadioModule radioModule, IBroadcastRadio service,
android.hardware.radio.ITunerCallback callback,
Object lock) {
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");
mLock = Objects.requireNonNull(lock, "lock cannot be null");
mLogger = new RadioLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
}
@@ -91,17 +89,19 @@ final class TunerSession extends ITuner.Stub {
mLogger.logRadioEvent("Close tuner session on error %d", error);
}
synchronized (mLock) {
if (mIsClosed) return;
if (error != null) {
try {
mCallback.onError(error);
} catch (RemoteException ex) {
Slogf.w(TAG, ex, "mCallback.onError(%s) failed", error);
}
if (mIsClosed) {
return;
}
mIsClosed = true;
mModule.onTunerSessionClosed(this);
}
if (error != null) {
try {
mCallback.onError(error);
} catch (RemoteException ex) {
Slogf.w(TAG, ex, "mCallback.onError(%s) failed", error);
}
}
mModule.onTunerSessionClosed(this);
}
@Override

View File

@@ -36,7 +36,7 @@ public class BroadcastRadioService {
*/
private final long mNativeContext = nativeInit();
private final Object mLock;
private final Object mLock = new Object();
@Override
protected void finalize() throws Throwable {
@@ -50,14 +50,6 @@ public class BroadcastRadioService {
private native Tuner nativeOpenTuner(long nativeContext, int moduleId,
RadioManager.BandConfig config, boolean withAudio, ITunerCallback callback);
/**
* Constructor. should pass
* {@code com.android.server.broadcastradio.BroadcastRadioService#mLock} for lock.
*/
public BroadcastRadioService(Object lock) {
mLock = lock;
}
public @NonNull List<RadioManager.ModuleProperties> loadModules() {
synchronized (mLock) {
return Objects.requireNonNull(nativeLoadModules(mNativeContext));

View File

@@ -43,13 +43,16 @@ import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
public class BroadcastRadioService {
/**
* Broadcast radio service using BroadcastRadio HIDL 2.0 HAL
*/
public final class BroadcastRadioService {
private static final String TAG = "BcRadio2Srv";
private final Object mLock;
private final Object mLock = new Object();
@GuardedBy("mLock")
private int mNextModuleId = 0;
private int mNextModuleId;
@GuardedBy("mLock")
private final Map<String, Integer> mServiceNameToModuleIdMap = new HashMap<>();
@@ -72,7 +75,7 @@ public class BroadcastRadioService {
moduleId = mNextModuleId;
}
RadioModule module = RadioModule.tryLoadingModule(moduleId, serviceName, mLock);
RadioModule module = RadioModule.tryLoadingModule(moduleId, serviceName);
if (module == null) {
return;
}
@@ -120,9 +123,8 @@ public class BroadcastRadioService {
}
};
public BroadcastRadioService(int nextModuleId, Object lock) {
public BroadcastRadioService(int nextModuleId) {
mNextModuleId = nextModuleId;
mLock = lock;
try {
IServiceManager manager = IServiceManager.getService();
if (manager == null) {
@@ -136,9 +138,8 @@ public class BroadcastRadioService {
}
@VisibleForTesting
BroadcastRadioService(int nextModuleId, Object lock, IServiceManager manager) {
BroadcastRadioService(int nextModuleId, IServiceManager manager) {
mNextModuleId = nextModuleId;
mLock = lock;
Objects.requireNonNull(manager, "Service manager cannot be null");
try {
manager.registerForNotifications(IBroadcastRadio.kInterfaceName, "", mServiceListener);
@@ -180,7 +181,7 @@ public class BroadcastRadioService {
throw new IllegalArgumentException("Non-audio sessions not supported with HAL 2.0");
}
RadioModule module = null;
RadioModule module;
synchronized (mLock) {
module = mModules.get(moduleId);
if (module == null) {

View File

@@ -60,7 +60,7 @@ final class RadioModule {
@NonNull private final IBroadcastRadio mService;
@NonNull private final RadioManager.ModuleProperties mProperties;
private final Object mLock;
private final Object mLock = new Object();
@NonNull private final Handler mHandler;
@NonNull private final RadioEventLogger mEventLogger;
@@ -75,7 +75,7 @@ final class RadioModule {
private RadioManager.ProgramInfo mCurrentProgramInfo = null;
@GuardedBy("mLock")
private final ProgramInfoCache mProgramInfoCache = new ProgramInfoCache(null);
private final ProgramInfoCache mProgramInfoCache = new ProgramInfoCache(/* filter= */ null);
@GuardedBy("mLock")
private android.hardware.radio.ProgramList.Filter mUnionOfAidlProgramFilters = null;
@@ -84,47 +84,59 @@ final class RadioModule {
private final ITunerCallback mHalTunerCallback = new ITunerCallback.Stub() {
@Override
public void onTuneFailed(int result, ProgramSelector programSelector) {
lockAndFireLater(() -> {
fireLater(() -> {
android.hardware.radio.ProgramSelector csel =
Convert.programSelectorFromHal(programSelector);
fanoutAidlCallbackLocked(cb -> cb.onTuneFailed(result, csel));
synchronized (mLock) {
fanoutAidlCallbackLocked(cb -> cb.onTuneFailed(result, csel));
}
});
}
@Override
public void onCurrentProgramInfoChanged(ProgramInfo halProgramInfo) {
lockAndFireLater(() -> {
mCurrentProgramInfo = Convert.programInfoFromHal(halProgramInfo);
fanoutAidlCallbackLocked(cb -> cb.onCurrentProgramInfoChanged(mCurrentProgramInfo));
fireLater(() -> {
synchronized (mLock) {
mCurrentProgramInfo = Convert.programInfoFromHal(halProgramInfo);
RadioManager.ProgramInfo currentProgramInfo = mCurrentProgramInfo;
fanoutAidlCallbackLocked(cb -> cb.onCurrentProgramInfoChanged(
currentProgramInfo));
}
});
}
@Override
public void onProgramListUpdated(ProgramListChunk programListChunk) {
lockAndFireLater(() -> {
fireLater(() -> {
android.hardware.radio.ProgramList.Chunk chunk =
Convert.programListChunkFromHal(programListChunk);
mProgramInfoCache.filterAndApplyChunk(chunk);
synchronized (mLock) {
mProgramInfoCache.filterAndApplyChunk(chunk);
for (TunerSession tunerSession : mAidlTunerSessions) {
tunerSession.onMergedProgramListUpdateFromHal(chunk);
for (TunerSession tunerSession : mAidlTunerSessions) {
tunerSession.onMergedProgramListUpdateFromHal(chunk);
}
}
});
}
@Override
public void onAntennaStateChange(boolean connected) {
lockAndFireLater(() -> {
mAntennaConnected = connected;
fanoutAidlCallbackLocked(cb -> cb.onAntennaState(connected));
fireLater(() -> {
synchronized (mLock) {
mAntennaConnected = connected;
fanoutAidlCallbackLocked(cb -> cb.onAntennaState(connected));
}
});
}
@Override
public void onParametersUpdated(ArrayList<VendorKeyValue> parameters) {
lockAndFireLater(() -> {
fireLater(() -> {
Map<String, String> cparam = Convert.vendorInfoFromHal(parameters);
fanoutAidlCallbackLocked(cb -> cb.onParametersUpdated(cparam));
synchronized (mLock) {
fanoutAidlCallbackLocked(cb -> cb.onParametersUpdated(cparam));
}
});
}
};
@@ -135,17 +147,15 @@ final class RadioModule {
@VisibleForTesting
RadioModule(@NonNull IBroadcastRadio service,
@NonNull RadioManager.ModuleProperties properties, @NonNull Object lock) {
@NonNull RadioManager.ModuleProperties properties) {
mProperties = Objects.requireNonNull(properties);
mService = Objects.requireNonNull(service);
mLock = Objects.requireNonNull(lock);
mHandler = new Handler(Looper.getMainLooper());
mEventLogger = new RadioEventLogger(TAG, RADIO_EVENT_LOGGER_QUEUE_SIZE);
}
@Nullable
static RadioModule tryLoadingModule(int idx, @NonNull String fqName,
Object lock) {
static RadioModule tryLoadingModule(int idx, @NonNull String fqName) {
try {
Slog.i(TAG, "Try loading module for idx " + idx + ", fqName " + fqName);
IBroadcastRadio service = IBroadcastRadio.getService(fqName);
@@ -167,7 +177,7 @@ final class RadioModule {
RadioManager.ModuleProperties prop = Convert.propertiesFromHal(idx, fqName,
service.getProperties(), amfmConfig.value, dabConfig.value);
return new RadioModule(service, prop, lock);
return new RadioModule(service, prop);
} catch (RemoteException ex) {
Slog.e(TAG, "Failed to load module " + fqName, ex);
return null;
@@ -196,8 +206,7 @@ final class RadioModule {
});
mHalTunerSession = Objects.requireNonNull(hwSession.value);
}
TunerSession tunerSession = new TunerSession(this, mHalTunerSession, userCb,
mLock);
TunerSession tunerSession = new TunerSession(this, mHalTunerSession, userCb);
mAidlTunerSessions.add(tunerSession);
// Propagate state to new client. Note: These callbacks are invoked while holding mLock
@@ -229,6 +238,7 @@ final class RadioModule {
}
}
@GuardedBy("mLock")
@Nullable
private android.hardware.radio.ProgramList.Filter
buildUnionOfTunerSessionFiltersLocked() {
@@ -281,6 +291,7 @@ final class RadioModule {
}
}
@GuardedBy("mLock")
private void onTunerSessionProgramListFilterChangedLocked(@Nullable TunerSession session) {
android.hardware.radio.ProgramList.Filter newFilter =
buildUnionOfTunerSessionFiltersLocked();
@@ -325,6 +336,7 @@ final class RadioModule {
}
}
@GuardedBy("mLock")
private void onTunerSessionsClosedLocked(TunerSession... tunerSessions) {
for (TunerSession tunerSession : tunerSessions) {
mAidlTunerSessions.remove(tunerSession);
@@ -342,12 +354,8 @@ final 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();
}
});
private void fireLater(Runnable r) {
mHandler.post(() -> r.run());
}
interface AidlCallbackRunnable {
@@ -356,9 +364,14 @@ final class RadioModule {
// Invokes runnable with each TunerSession currently open.
void fanoutAidlCallback(AidlCallbackRunnable runnable) {
lockAndFireLater(() -> fanoutAidlCallbackLocked(runnable));
fireLater(() -> {
synchronized (mLock) {
fanoutAidlCallbackLocked(runnable);
}
});
}
@GuardedBy("mLock")
private void fanoutAidlCallbackLocked(AidlCallbackRunnable runnable) {
List<TunerSession> deadSessions = null;
for (TunerSession tunerSession : mAidlTunerSessions) {
@@ -399,12 +412,10 @@ final class RadioModule {
}
};
synchronized (mLock) {
mService.registerAnnouncementListener(enabledList, hwListener, (result, closeHnd) -> {
halResult.value = result;
hwCloseHandle.value = closeHnd;
});
}
mService.registerAnnouncementListener(enabledList, hwListener, (result, closeHandle) -> {
halResult.value = result;
hwCloseHandle.value = closeHandle;
});
Convert.throwOnError("addAnnouncementListener", halResult.value);
return new android.hardware.radio.ICloseHandle.Stub() {
@@ -424,12 +435,10 @@ final class RadioModule {
if (id == 0) throw new IllegalArgumentException("Image ID is missing");
byte[] rawImage;
synchronized (mLock) {
List<Byte> rawList = Utils.maybeRethrow(() -> mService.getImage(id));
rawImage = new byte[rawList.size()];
for (int i = 0; i < rawList.size(); i++) {
rawImage[i] = rawList.get(i);
}
List<Byte> rawList = Utils.maybeRethrow(() -> mService.getImage(id));
rawImage = new byte[rawList.size()];
for (int i = 0; i < rawList.size(); i++) {
rawImage[i] = rawList.get(i);
}
if (rawImage == null || rawImage.length == 0) return null;
@@ -440,17 +449,17 @@ final class RadioModule {
void dumpInfo(IndentingPrintWriter pw) {
pw.printf("RadioModule\n");
pw.increaseIndent();
pw.printf("BroadcastRadioService: %s\n", mService);
pw.printf("Properties: %s\n", mProperties);
synchronized (mLock) {
pw.printf("BroadcastRadioService: %s\n", mService);
pw.printf("Properties: %s\n", mProperties);
pw.printf("HIDL2.0 HAL TunerSession: %s\n", mHalTunerSession);
pw.printf("HIDL 2.0 HAL TunerSession: %s\n", mHalTunerSession);
pw.printf("Is antenna connected? ");
if (mAntennaConnected == null) {
pw.printf("null\n");
} else {
pw.printf("%s\n", mAntennaConnected ? "Yes" : "No");
}
pw.printf("current ProgramInfo: %s\n", mCurrentProgramInfo);
pw.printf("Current ProgramInfo: %s\n", mCurrentProgramInfo);
pw.printf("ProgramInfoCache: %s\n", mProgramInfoCache);
pw.printf("Union of AIDL ProgramFilters: %s\n", mUnionOfAidlProgramFilters);
pw.printf("AIDL TunerSessions:\n");

View File

@@ -33,6 +33,7 @@ import android.util.MutableBoolean;
import android.util.MutableInt;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.server.broadcastradio.RadioServiceUserController;
import com.android.server.utils.Slogf;
@@ -46,26 +47,28 @@ class TunerSession extends ITuner.Stub {
private static final String kAudioDeviceName = "Radio tuner source";
private static final int TUNER_EVENT_LOGGER_QUEUE_SIZE = 25;
private final Object mLock;
private final Object mLock = new Object();
@NonNull private final RadioEventLogger mEventLogger;
private final RadioModule mModule;
private final ITunerSession mHwSession;
final android.hardware.radio.ITunerCallback mCallback;
@GuardedBy("mLock")
private boolean mIsClosed = false;
@GuardedBy("mLock")
private boolean mIsMuted = false;
@GuardedBy("mLock")
private ProgramInfoCache mProgramInfoCache = null;
// necessary only for older APIs compatibility
private RadioManager.BandConfig mDummyConfig = null;
TunerSession(@NonNull RadioModule module, @NonNull ITunerSession hwSession,
@NonNull android.hardware.radio.ITunerCallback callback,
@NonNull Object lock) {
@NonNull android.hardware.radio.ITunerCallback callback) {
mModule = Objects.requireNonNull(module);
mHwSession = Objects.requireNonNull(hwSession);
mCallback = Objects.requireNonNull(callback);
mLock = Objects.requireNonNull(lock);
mEventLogger = new RadioEventLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
}
@@ -86,23 +89,26 @@ class TunerSession extends ITuner.Stub {
mEventLogger.logRadioEvent("Close on error %d", error);
synchronized (mLock) {
if (mIsClosed) return;
if (error != null) {
try {
mCallback.onError(error);
} catch (RemoteException ex) {
Slog.w(TAG, "mCallback.onError() failed: ", ex);
}
}
mIsClosed = true;
mModule.onTunerSessionClosed(this);
}
if (error != null) {
try {
mCallback.onError(error);
} catch (RemoteException ex) {
Slog.w(TAG, "mCallback.onError() failed: ", ex);
}
}
mModule.onTunerSessionClosed(this);
}
@Override
public boolean isClosed() {
return mIsClosed;
synchronized (mLock) {
return mIsClosed;
}
}
@GuardedBy("mLock")
private void checkNotClosedLocked() {
if (mIsClosed) {
throw new IllegalStateException("Tuner is closed, no further operations are allowed");
@@ -118,9 +124,9 @@ class TunerSession extends ITuner.Stub {
synchronized (mLock) {
checkNotClosedLocked();
mDummyConfig = Objects.requireNonNull(config);
Slog.i(TAG, "Ignoring setConfiguration - not applicable for broadcastradio HAL 2.0");
mModule.fanoutAidlCallback(cb -> cb.onConfigurationChanged(config));
}
Slog.i(TAG, "Ignoring setConfiguration - not applicable for broadcastradio HAL 2.0");
mModule.fanoutAidlCallback(cb -> cb.onConfigurationChanged(config));
}
@Override
@@ -137,8 +143,8 @@ class TunerSession extends ITuner.Stub {
checkNotClosedLocked();
if (mIsMuted == mute) return;
mIsMuted = mute;
Slog.w(TAG, "Mute via RadioService is not implemented - please handle it via app");
}
Slog.w(TAG, "Mute via RadioService is not implemented - please handle it via app");
}
@Override
@@ -383,8 +389,8 @@ class TunerSession extends ITuner.Stub {
void dumpInfo(IndentingPrintWriter pw) {
pw.printf("TunerSession\n");
pw.increaseIndent();
pw.printf("HIDL HAL Session: %s\n", mHwSession);
synchronized (mLock) {
pw.printf("HIDL HAL Session: %s\n", mHwSession);
pw.printf("Is session closed? %s\n", mIsClosed ? "Yes" : "No");
pw.printf("Is muted? %s\n", mIsMuted ? "Yes" : "No");
pw.printf("ProgramInfoCache: %s\n", mProgramInfoCache);