diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java index 635d1e7927150..93214e5a69448 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImplTest.java @@ -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); } diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java index 3bf993c07aed6..a29e9c5c9bb13 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java @@ -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); diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/BroadcastRadioServiceHidlTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/BroadcastRadioServiceHidlTest.java index 4d0b753b0acc1..99e70436ac955 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/BroadcastRadioServiceHidlTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/BroadcastRadioServiceHidlTest.java @@ -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); diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java index eadf226b01ce2..ec55ddbe1a4a6 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java @@ -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 = diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java index d1043595535a2..e3c9faa601e79 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java @@ -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); diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java index 936e606fcb76d..8884053bb58c0 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java @@ -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); diff --git a/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java b/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java new file mode 100644 index 0000000000000..38b3233953293 --- /dev/null +++ b/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java @@ -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; + } +} diff --git a/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java b/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java index 4fcfea2d0e070..1d7112133b486 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/BroadcastRadioServiceImpl.java @@ -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 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) { diff --git a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java index d4c7242f71a92..eb9dafbe5281b 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java @@ -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 idTypes = null; Set 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"); diff --git a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java index 7c26a8741a03a..d33633c435b10 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java @@ -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 setParameters(Map 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 { diff --git a/services/core/java/com/android/server/broadcastradio/hal1/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal1/BroadcastRadioService.java index 5da60328cd709..e50c6e8c21b8d 100644 --- a/services/core/java/com/android/server/broadcastradio/hal1/BroadcastRadioService.java +++ b/services/core/java/com/android/server/broadcastradio/hal1/BroadcastRadioService.java @@ -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); } diff --git a/services/core/java/com/android/server/broadcastradio/hal1/Convert.java b/services/core/java/com/android/server/broadcastradio/hal1/Convert.java index 80c776254d981..219ee4c3229ae 100644 --- a/services/core/java/com/android/server/broadcastradio/hal1/Convert.java +++ b/services/core/java/com/android/server/broadcastradio/hal1/Convert.java @@ -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. diff --git a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java index e7118ad72bf42..ed8a37aab14a3 100644 --- a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java +++ b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java @@ -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(); diff --git a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java index 867d5b4b6f49b..0cc3833896bec 100644 --- a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java +++ b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java @@ -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. diff --git a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java index 4c3760928df32..3d6962783f4a5 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java @@ -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) { diff --git a/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java b/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java index 6654c0c2304d2..9831af6b523ea 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java @@ -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. diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java index 5913e0685eb4f..cf1b504037bc9 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java @@ -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 idTypes = null; Set 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 enabledList = new ArrayList<>(); for (int type : enabledTypes) { diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java index 918dc98e3a9e7..12211eed47fda 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java @@ -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 setParameters(Map 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(