Merge "Add user control for broadcast radio HAL client"
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user