Merge "Add user control for broadcast radio HAL client"

This commit is contained in:
Weilin Xu
2022-11-21 23:56:04 +00:00
committed by Android (Google) Code Review
18 changed files with 295 additions and 41 deletions

View File

@@ -39,6 +39,7 @@ import android.os.ServiceManager;
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
import com.android.server.broadcastradio.RadioServiceUserController;
import org.junit.Test;
import org.mockito.Mock;
@@ -81,7 +82,8 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
@Override
protected void initializeSession(StaticMockitoSessionBuilder builder) {
builder.spyStatic(ServiceManager.class)
.spyStatic(RadioModule.class);
.spyStatic(RadioModule.class)
.spyStatic(RadioServiceUserController.class);
}
@Test
@@ -150,6 +152,7 @@ public final class BroadcastRadioServiceImplTest extends ExtendedRadioMockitoTes
}
private void createBroadcastRadioService() throws RemoteException {
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
mockServiceManager();
mBroadcastRadioService = new BroadcastRadioServiceImpl(SERVICE_LIST);
}

View File

@@ -16,6 +16,8 @@
package com.android.server.broadcastradio.aidl;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
@@ -44,12 +46,14 @@ import android.os.ServiceSpecificException;
import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
import com.android.server.broadcastradio.RadioServiceUserController;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.verification.VerificationWithTimeout;
import java.util.ArrayList;
@@ -59,8 +63,7 @@ import java.util.Map;
/**
* Tests for AIDL HAL TunerSession.
*/
@RunWith(MockitoJUnitRunner.class)
public final class TunerSessionTest {
public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
private static final VerificationWithTimeout CALLBACK_TIMEOUT =
timeout(/* millis= */ 200);
@@ -91,8 +94,15 @@ public final class TunerSessionTest {
private TunerSession[] mTunerSessions;
@Override
protected void initializeSession(StaticMockitoSessionBuilder builder) {
builder.spyStatic(RadioServiceUserController.class);
}
@Before
public void setup() throws Exception {
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
mRadioModule = new RadioModule(mBroadcastRadioMock,
AidlTestUtils.makeDefaultModuleProperties(), mLock);

View File

@@ -43,6 +43,7 @@ import android.os.RemoteException;
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
import com.android.server.broadcastradio.RadioServiceUserController;
import org.junit.Test;
import org.mockito.Mock;
@@ -92,7 +93,8 @@ public final class BroadcastRadioServiceHidlTest extends ExtendedRadioMockitoTes
@Override
protected void initializeSession(StaticMockitoSessionBuilder builder) {
builder.spyStatic(RadioModule.class);
builder.spyStatic(RadioModule.class)
.spyStatic(RadioServiceUserController.class);
}
@Test
@@ -181,6 +183,8 @@ public final class BroadcastRadioServiceHidlTest extends ExtendedRadioMockitoTes
}
private void createBroadcastRadioService() throws RemoteException {
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
mockServiceManager();
mBroadcastRadioService = new BroadcastRadioService(/* nextModuleId= */ FM_RADIO_MODULE_ID,
mLock, mServiceManagerMock);

View File

@@ -25,6 +25,8 @@ import android.test.suitebuilder.annotation.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,7 +39,7 @@ import java.util.Set;
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
public class ProgramInfoCacheTest {
public class ProgramInfoCacheTest extends ExtendedRadioMockitoTestCase {
private static final String TAG = "BroadcastRadioTests.ProgramInfoCache";
private final ProgramSelector.Identifier mAmFmIdentifier =

View File

@@ -15,6 +15,8 @@
*/
package com.android.server.broadcastradio.hal2;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
@@ -34,15 +36,14 @@ import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.os.RemoteException;
import android.test.suitebuilder.annotation.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
import com.android.server.broadcastradio.RadioServiceUserController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
import org.mockito.verification.VerificationWithTimeout;
@@ -53,9 +54,7 @@ import java.util.List;
/**
* Tests for v2 HAL RadioModule.
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
public class StartProgramListUpdatesFanoutTest {
public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestCase {
private static final String TAG = "BroadcastRadioTests.hal2.StartProgramListUpdatesFanout";
private static final VerificationWithTimeout CB_TIMEOUT = timeout(500);
@@ -91,9 +90,14 @@ public class StartProgramListUpdatesFanoutTest {
private final RadioManager.ProgramInfo mDabEnsembleInfo = TestUtils.makeProgramInfo(
ProgramSelector.PROGRAM_TYPE_DAB, mDabEnsembleIdentifier, 0);
@Override
protected void initializeSession(StaticMockitoSessionBuilder builder) {
builder.spyStatic(RadioServiceUserController.class);
}
@Before
public void setup() throws RemoteException {
MockitoAnnotations.initMocks(this);
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
mRadioModule = new RadioModule(mBroadcastRadioMock,
TestUtils.makeDefaultModuleProperties(), mLock);

View File

@@ -16,6 +16,8 @@
package com.android.server.broadcastradio.hal2;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
@@ -45,6 +47,10 @@ import android.hardware.radio.RadioTuner;
import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
import com.android.server.broadcastradio.RadioServiceUserController;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -61,7 +67,7 @@ import java.util.Map;
* Tests for HIDL HAL TunerSession.
*/
@RunWith(MockitoJUnitRunner.class)
public final class TunerSessionHidlTest {
public final class TunerSessionHidlTest extends ExtendedRadioMockitoTestCase {
private static final VerificationWithTimeout CALLBACK_TIMEOUT =
timeout(/* millis= */ 200);
@@ -88,8 +94,15 @@ public final class TunerSessionHidlTest {
@Mock ITunerSession mHalTunerSessionMock;
private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks;
@Override
protected void initializeSession(StaticMockitoSessionBuilder builder) {
builder.spyStatic(RadioServiceUserController.class);
}
@Before
public void setup() throws Exception {
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
mRadioModule = new RadioModule(mBroadcastRadioMock,
TestUtils.makeDefaultModuleProperties(), mLock);

View File

@@ -0,0 +1,56 @@
/**
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.broadcastradio;
import android.app.ActivityManager;
import android.os.Binder;
import android.os.UserHandle;
/**
* Controller to handle users in {@link com.android.server.broadcastradio.BroadcastRadioService}
*/
public final class RadioServiceUserController {
private RadioServiceUserController() {
throw new UnsupportedOperationException(
"RadioServiceUserController class is noninstantiable");
}
/**
* Check if the user calling the method in Broadcast Radio Service is the current user or the
* system user.
*
* @return {@code true} if the user calling this method is the current user of system user,
* {@code false} otherwise.
*/
public static boolean isCurrentOrSystemUser() {
int callingUser = Binder.getCallingUserHandle().getIdentifier();
final long identity = Binder.clearCallingIdentity();
try {
int currentUser = ActivityManager.getCurrentUser();
if (callingUser != currentUser && callingUser != UserHandle.USER_SYSTEM) {
return false;
}
return true;
} catch (RuntimeException e) {
// Activity manager not running, nothing we can do assume user 0.
} finally {
Binder.restoreCallingIdentity(identity);
}
return false;
}
}

View File

@@ -34,6 +34,7 @@ import android.util.Log;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.broadcastradio.RadioServiceUserController;
import com.android.server.utils.Slogf;
import java.util.ArrayList;
@@ -149,8 +150,7 @@ public final class BroadcastRadioServiceImpl {
public BroadcastRadioServiceImpl(ArrayList<String> serviceNameList) {
mNextModuleId = 0;
if (DEBUG) {
Slogf.d(TAG, "Initializing BroadcastRadioServiceImpl %s",
IBroadcastRadio.DESCRIPTOR);
Slogf.d(TAG, "Initializing BroadcastRadioServiceImpl %s", IBroadcastRadio.DESCRIPTOR);
}
for (int i = 0; i < serviceNameList.size(); i++) {
try {
@@ -203,6 +203,10 @@ public final class BroadcastRadioServiceImpl {
if (DEBUG) {
Slogf.d(TAG, "Open AIDL radio session");
}
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.e(TAG, "Cannot open tuner on AIDL HAL client for non-current user");
throw new IllegalStateException("Cannot open session for non-current user");
}
Objects.requireNonNull(callback);
if (!withAudio) {

View File

@@ -175,7 +175,7 @@ final class RadioModule {
}
@Nullable
public static RadioModule tryLoadingModule(int moduleId, String moduleName,
static RadioModule tryLoadingModule(int moduleId, String moduleName,
IBinder serviceBinder, Object lock) {
try {
Slogf.i(TAG, "Try loading module for module id = %d, module name = %s",
@@ -213,11 +213,11 @@ final class RadioModule {
}
}
public IBroadcastRadio getService() {
IBroadcastRadio getService() {
return mService;
}
public RadioManager.ModuleProperties getProperties() {
RadioManager.ModuleProperties getProperties() {
return mProperties;
}
@@ -227,7 +227,7 @@ final class RadioModule {
}
}
public TunerSession openSession(android.hardware.radio.ITunerCallback userCb)
TunerSession openSession(android.hardware.radio.ITunerCallback userCb)
throws RemoteException {
mLogger.logRadioEvent("Open TunerSession");
TunerSession tunerSession;
@@ -252,7 +252,7 @@ final class RadioModule {
return tunerSession;
}
public void closeSessions(int error) {
void closeSessions(int error) {
mLogger.logRadioEvent("Close TunerSessions %d", error);
// TunerSession.close() must be called without mAidlTunerSessions locked because
// it can call onTunerSessionClosed(). Therefore, the contents of mAidlTunerSessions
@@ -275,8 +275,7 @@ final class RadioModule {
@GuardedBy("mLock")
@Nullable
private android.hardware.radio.ProgramList.Filter
buildUnionOfTunerSessionFiltersLocked() {
private android.hardware.radio.ProgramList.Filter buildUnionOfTunerSessionFiltersLocked() {
Set<Integer> idTypes = null;
Set<android.hardware.radio.ProgramSelector.Identifier> ids = null;
boolean includeCategories = false;
@@ -423,7 +422,7 @@ final class RadioModule {
}
}
public android.hardware.radio.ICloseHandle addAnnouncementListener(
android.hardware.radio.ICloseHandle addAnnouncementListener(
android.hardware.radio.IAnnouncementListener listener,
int[] enabledTypes) throws RemoteException {
mLogger.logRadioEvent("Add AnnouncementListener");

View File

@@ -26,10 +26,12 @@ import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
import com.android.server.broadcastradio.RadioServiceUserController;
import com.android.server.utils.Slogf;
import java.util.List;
@@ -70,7 +72,7 @@ final class TunerSession extends ITuner.Stub {
@Override
public void close() {
mLogger.logRadioEvent("Close tuner session");
mLogger.logRadioEvent("Close tuner");
close(null);
}
@@ -118,6 +120,10 @@ final class TunerSession extends ITuner.Stub {
@Override
public void setConfiguration(RadioManager.BandConfig config) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot set configuration for AIDL HAL client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
mPlaceHolderConfig = Objects.requireNonNull(config, "config cannot be null");
@@ -157,6 +163,10 @@ final class TunerSession extends ITuner.Stub {
public void step(boolean directionDown, boolean skipSubChannel) throws RemoteException {
mLogger.logRadioEvent("Step with direction %s, skipSubChannel? %s",
directionDown ? "down" : "up", skipSubChannel ? "yes" : "no");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot step on AIDL HAL client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
try {
@@ -171,6 +181,10 @@ final class TunerSession extends ITuner.Stub {
public void scan(boolean directionDown, boolean skipSubChannel) throws RemoteException {
mLogger.logRadioEvent("Scan with direction %s, skipSubChannel? %s",
directionDown ? "down" : "up", skipSubChannel ? "yes" : "no");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot scan on AIDL HAL client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
try {
@@ -184,6 +198,10 @@ final class TunerSession extends ITuner.Stub {
@Override
public void tune(ProgramSelector selector) throws RemoteException {
mLogger.logRadioEvent("Tune with selector %s", selector);
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot tune on AIDL HAL client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
try {
@@ -197,6 +215,10 @@ final class TunerSession extends ITuner.Stub {
@Override
public void cancel() {
Slogf.i(TAG, "Cancel");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot cancel on AIDL HAL client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
try {
@@ -223,6 +245,10 @@ final class TunerSession extends ITuner.Stub {
@Override
public boolean startBackgroundScan() {
Slogf.i(TAG, "Explicit background scan trigger is not supported with HAL AIDL");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot start background scan on AIDL HAL client from non-current user");
return false;
}
mModule.fanoutAidlCallback(ITunerCallback::onBackgroundScanComplete);
return true;
}
@@ -230,6 +256,11 @@ final class TunerSession extends ITuner.Stub {
@Override
public void startProgramListUpdates(ProgramList.Filter filter) throws RemoteException {
mLogger.logRadioEvent("Start programList updates %s", filter);
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG,
"Cannot start program list updates on AIDL HAL client from non-current user");
return;
}
// If the AIDL client provides a null filter, it wants all updates, so use the most broad
// filter.
if (filter == null) {
@@ -291,6 +322,11 @@ final class TunerSession extends ITuner.Stub {
@Override
public void stopProgramListUpdates() throws RemoteException {
mLogger.logRadioEvent("Stop programList updates");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG,
"Cannot stop program list updates on AIDL HAL client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
mProgramInfoCache = null;
@@ -331,6 +367,10 @@ final class TunerSession extends ITuner.Stub {
public void setConfigFlag(int flag, boolean value) throws RemoteException {
mLogger.logRadioEvent("set ConfigFlag %s to %b ",
ConfigFlag.$.toString(flag), value);
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot set config flag for AIDL HAL client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
try {
@@ -344,6 +384,10 @@ final class TunerSession extends ITuner.Stub {
@Override
public Map<String, String> setParameters(Map<String, String> parameters) {
mLogger.logRadioEvent("Set parameters ");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot set parameters for AIDL HAL client from non-current user");
return new ArrayMap<>();
}
synchronized (mLock) {
checkNotClosedLocked();
try {

View File

@@ -21,10 +21,16 @@ import android.hardware.radio.ITuner;
import android.hardware.radio.ITunerCallback;
import android.hardware.radio.RadioManager;
import com.android.server.broadcastradio.RadioServiceUserController;
import com.android.server.utils.Slogf;
import java.util.List;
import java.util.Objects;
public class BroadcastRadioService {
private static final String TAG = "BcRadio1Srv";
/**
* This field is used by native code, do not access or modify.
*/
@@ -48,7 +54,7 @@ public class BroadcastRadioService {
* Constructor. should pass
* {@code com.android.server.broadcastradio.BroadcastRadioService#mLock} for lock.
*/
public BroadcastRadioService(@NonNull Object lock) {
public BroadcastRadioService(Object lock) {
mLock = lock;
}
@@ -59,7 +65,11 @@ public class BroadcastRadioService {
}
public ITuner openTuner(int moduleId, RadioManager.BandConfig bandConfig,
boolean withAudio, @NonNull ITunerCallback callback) {
boolean withAudio, ITunerCallback callback) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.e(TAG, "Cannot open tuner on HAL 1.x client for non-current user");
throw new IllegalStateException("Cannot open tuner for non-current user");
}
synchronized (mLock) {
return nativeOpenTuner(mNativeContext, moduleId, bandConfig, withAudio, callback);
}

View File

@@ -24,7 +24,8 @@ import java.util.Map;
import java.util.Set;
class Convert {
private static final String TAG = "BroadcastRadioService.Convert";
private static final String TAG = "BcRadio1Srv.Convert";
/**
* Converts string map to an array that's easily accessible by native code.

View File

@@ -28,11 +28,15 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.broadcastradio.RadioServiceUserController;
import com.android.server.utils.Slogf;
import java.util.List;
import java.util.Map;
class Tuner extends ITuner.Stub {
private static final String TAG = "BroadcastRadioService.Tuner";
private static final String TAG = "BcRadio1Srv.Tuner";
/**
* This field is used by native code, do not access or modify.
@@ -124,6 +128,10 @@ class Tuner extends ITuner.Stub {
@Override
public void setConfiguration(RadioManager.BandConfig config) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot set configuration for HAL 1.x client from non-current user");
return;
}
if (config == null) {
throw new IllegalArgumentException("The argument must not be a null pointer");
}
@@ -169,6 +177,10 @@ class Tuner extends ITuner.Stub {
@Override
public void step(boolean directionDown, boolean skipSubChannel) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot step on HAL 1.x client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
if (!checkConfiguredLocked()) return;
@@ -178,6 +190,10 @@ class Tuner extends ITuner.Stub {
@Override
public void scan(boolean directionDown, boolean skipSubChannel) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot scan on HAL 1.x client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
if (!checkConfiguredLocked()) return;
@@ -187,6 +203,10 @@ class Tuner extends ITuner.Stub {
@Override
public void tune(ProgramSelector selector) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot tune on HAL 1.x client from non-current user");
return;
}
if (selector == null) {
throw new IllegalArgumentException("The argument must not be a null pointer");
}
@@ -200,6 +220,10 @@ class Tuner extends ITuner.Stub {
@Override
public void cancel() {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot cancel on HAL 1.x client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
nativeCancel(mNativeContext);
@@ -208,6 +232,10 @@ class Tuner extends ITuner.Stub {
@Override
public void cancelAnnouncement() {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot cancel announcement on HAL 1.x client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
nativeCancelAnnouncement(mNativeContext);
@@ -233,6 +261,11 @@ class Tuner extends ITuner.Stub {
@Override
public boolean startBackgroundScan() {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG,
"Cannot start background scan on HAL 1.x client from non-current user");
return false;
}
synchronized (mLock) {
checkNotClosedLocked();
return nativeStartBackgroundScan(mNativeContext);
@@ -253,11 +286,21 @@ class Tuner extends ITuner.Stub {
@Override
public void startProgramListUpdates(ProgramList.Filter filter) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG,
"Cannot start program list updates on HAL 1.x client from non-current user");
return;
}
mTunerCallback.startProgramListUpdates(filter);
}
@Override
public void stopProgramListUpdates() {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG,
"Cannot stop program list updates on HAL 1.x client from non-current user");
return;
}
mTunerCallback.stopProgramListUpdates();
}
@@ -279,6 +322,10 @@ class Tuner extends ITuner.Stub {
@Override
public void setConfigFlag(int flag, boolean value) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot set config flag for HAL 1.x client from non-current user");
return;
}
if (flag == RadioManager.CONFIG_FORCE_ANALOG) {
synchronized (mLock) {
checkNotClosedLocked();

View File

@@ -34,7 +34,8 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
class TunerCallback implements ITunerCallback {
private static final String TAG = "BroadcastRadioService.TunerCallback";
private static final String TAG = "BcRadio1Srv.TunerCallback";
/**
* This field is used by native code, do not access or modify.

View File

@@ -34,6 +34,8 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.broadcastradio.RadioServiceUserController;
import com.android.server.utils.Slogf;
import java.util.Collection;
import java.util.HashMap;
@@ -168,6 +170,10 @@ public class BroadcastRadioService {
public ITuner openSession(int moduleId, @Nullable RadioManager.BandConfig legacyConfig,
boolean withAudio, @NonNull ITunerCallback callback) throws RemoteException {
Slog.v(TAG, "Open HIDL 2.0 session with module id " + moduleId);
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.e(TAG, "Cannot open tuner on HAL 2.0 client for non-current user");
throw new IllegalStateException("Cannot open session for non-current user");
}
Objects.requireNonNull(callback);
if (!withAudio) {

View File

@@ -33,7 +33,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
class ProgramInfoCache {
final class ProgramInfoCache {
// Maximum number of RadioManager.ProgramInfo elements that will be put into a
// ProgramList.Chunk.mModified array. Used to try to ensure a single ProgramList.Chunk stays
// within the AIDL data size limit.

View File

@@ -53,7 +53,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
class RadioModule {
final class RadioModule {
private static final String TAG = "BcRadio2Srv.module";
private static final int RADIO_EVENT_LOGGER_QUEUE_SIZE = 25;
@@ -143,7 +143,8 @@ class RadioModule {
mEventLogger = new RadioEventLogger(TAG, RADIO_EVENT_LOGGER_QUEUE_SIZE);
}
public static @Nullable RadioModule tryLoadingModule(int idx, @NonNull String fqName,
@Nullable
static RadioModule tryLoadingModule(int idx, @NonNull String fqName,
Object lock) {
try {
Slog.i(TAG, "Try loading module for idx " + idx + ", fqName " + fqName);
@@ -173,7 +174,8 @@ class RadioModule {
}
}
public @NonNull IBroadcastRadio getService() {
@NonNull
IBroadcastRadio getService() {
return mService;
}
@@ -181,7 +183,7 @@ class RadioModule {
return mProperties;
}
public @NonNull TunerSession openSession(@NonNull android.hardware.radio.ITunerCallback userCb)
TunerSession openSession(@NonNull android.hardware.radio.ITunerCallback userCb)
throws RemoteException {
mEventLogger.logRadioEvent("Open TunerSession");
synchronized (mLock) {
@@ -211,7 +213,7 @@ class RadioModule {
}
}
public void closeSessions(Integer error) {
void closeSessions(Integer error) {
// Copy the contents of mAidlTunerSessions into a local array because TunerSession.close()
// must be called without mAidlTunerSessions locked because it can call
// onTunerSessionClosed().
@@ -227,7 +229,8 @@ class RadioModule {
}
}
private @Nullable android.hardware.radio.ProgramList.Filter
@Nullable
private android.hardware.radio.ProgramList.Filter
buildUnionOfTunerSessionFiltersLocked() {
Set<Integer> idTypes = null;
Set<android.hardware.radio.ProgramSelector.Identifier> ids = null;
@@ -378,8 +381,8 @@ class RadioModule {
}
}
public android.hardware.radio.ICloseHandle addAnnouncementListener(@NonNull int[] enabledTypes,
@NonNull android.hardware.radio.IAnnouncementListener listener) throws RemoteException {
android.hardware.radio.ICloseHandle addAnnouncementListener(int[] enabledTypes,
android.hardware.radio.IAnnouncementListener listener) throws RemoteException {
mEventLogger.logRadioEvent("Add AnnouncementListener");
ArrayList<Byte> enabledList = new ArrayList<>();
for (int type : enabledTypes) {

View File

@@ -27,11 +27,15 @@ import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.MutableBoolean;
import android.util.MutableInt;
import android.util.Slog;
import com.android.server.broadcastradio.RadioServiceUserController;
import com.android.server.utils.Slogf;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -107,6 +111,10 @@ class TunerSession extends ITuner.Stub {
@Override
public void setConfiguration(RadioManager.BandConfig config) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot set configuration for HAL 2.0 client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
mDummyConfig = Objects.requireNonNull(config);
@@ -145,6 +153,10 @@ class TunerSession extends ITuner.Stub {
public void step(boolean directionDown, boolean skipSubChannel) throws RemoteException {
mEventLogger.logRadioEvent("Step with direction %s, skipSubChannel? %s",
directionDown ? "down" : "up", skipSubChannel ? "yes" : "no");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot step on HAL 2.0 client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
int halResult = mHwSession.step(!directionDown);
@@ -156,6 +168,10 @@ class TunerSession extends ITuner.Stub {
public void scan(boolean directionDown, boolean skipSubChannel) throws RemoteException {
mEventLogger.logRadioEvent("Scan with direction %s, skipSubChannel? %s",
directionDown ? "down" : "up", skipSubChannel ? "yes" : "no");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot scan on HAL 2.0 client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
int halResult = mHwSession.scan(!directionDown, skipSubChannel);
@@ -166,6 +182,10 @@ class TunerSession extends ITuner.Stub {
@Override
public void tune(ProgramSelector selector) throws RemoteException {
mEventLogger.logRadioEvent("Tune with selector %s", selector);
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot tune on HAL 2.0 client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
int halResult = mHwSession.tune(Convert.programSelectorToHal(selector));
@@ -176,6 +196,10 @@ class TunerSession extends ITuner.Stub {
@Override
public void cancel() {
Slog.i(TAG, "Cancel");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot cancel on HAL 2.0 client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
Utils.maybeRethrow(mHwSession::cancel);
@@ -196,6 +220,11 @@ class TunerSession extends ITuner.Stub {
@Override
public boolean startBackgroundScan() {
Slog.i(TAG, "Explicit background scan trigger is not supported with HAL 2.0");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG,
"Cannot start background scan on HAL 2.0 client from non-current user");
return false;
}
mModule.fanoutAidlCallback(cb -> cb.onBackgroundScanComplete());
return true;
}
@@ -203,6 +232,11 @@ class TunerSession extends ITuner.Stub {
@Override
public void startProgramListUpdates(ProgramList.Filter filter) throws RemoteException {
mEventLogger.logRadioEvent("start programList updates %s", filter);
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG,
"Cannot start program list updates on HAL 2.0 client from non-current user");
return;
}
// If the AIDL client provides a null filter, it wants all updates, so use the most broad
// filter.
if (filter == null) {
@@ -262,6 +296,11 @@ class TunerSession extends ITuner.Stub {
@Override
public void stopProgramListUpdates() throws RemoteException {
mEventLogger.logRadioEvent("Stop programList updates");
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG,
"Cannot stop program list updates on HAL 2.0 client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
mProgramInfoCache = null;
@@ -308,6 +347,10 @@ class TunerSession extends ITuner.Stub {
@Override
public void setConfigFlag(int flag, boolean value) throws RemoteException {
mEventLogger.logRadioEvent("Set ConfigFlag %s = %b", ConfigFlag.toString(flag), value);
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot set config flag for HAL 2.0 client from non-current user");
return;
}
synchronized (mLock) {
checkNotClosedLocked();
int halResult = mHwSession.setConfigFlag(flag, value);
@@ -317,6 +360,10 @@ class TunerSession extends ITuner.Stub {
@Override
public Map<String, String> setParameters(Map<String, String> parameters) {
if (!RadioServiceUserController.isCurrentOrSystemUser()) {
Slogf.w(TAG, "Cannot set parameters for HAL 2.0 client from non-current user");
return new ArrayMap<>();
}
synchronized (mLock) {
checkNotClosedLocked();
return Convert.vendorInfoFromHal(Utils.maybeRethrow(