Merge changes from topic "system_mr2_media_content_control" into sc-dev
* changes: System MediaRouter2: Resolve API review Change MODIFY_AUDIO_ROUTING permission to MEDIA_CONTENT_CONTROL
This commit is contained in:
@@ -23307,6 +23307,7 @@ package android.media {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class MediaRouter2 {
|
public final class MediaRouter2 {
|
||||||
|
method @Nullable public android.media.MediaRouter2.RoutingController getController(@NonNull String);
|
||||||
method @NonNull public java.util.List<android.media.MediaRouter2.RoutingController> getControllers();
|
method @NonNull public java.util.List<android.media.MediaRouter2.RoutingController> getControllers();
|
||||||
method @NonNull public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context);
|
method @NonNull public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context);
|
||||||
method @NonNull public java.util.List<android.media.MediaRoute2Info> getRoutes();
|
method @NonNull public java.util.List<android.media.MediaRoute2Info> getRoutes();
|
||||||
|
|||||||
@@ -5327,12 +5327,11 @@ package android.media {
|
|||||||
public final class MediaRouter2 {
|
public final class MediaRouter2 {
|
||||||
method @NonNull public java.util.List<android.media.MediaRoute2Info> getAllRoutes();
|
method @NonNull public java.util.List<android.media.MediaRoute2Info> getAllRoutes();
|
||||||
method @Nullable public String getClientPackageName();
|
method @Nullable public String getClientPackageName();
|
||||||
method @Nullable public android.media.MediaRouter2.RoutingController getController(@NonNull String);
|
method @Nullable @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context, @NonNull String);
|
||||||
method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static android.media.MediaRouter2 getInstance(@NonNull android.content.Context, @NonNull String);
|
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void setRouteVolume(@NonNull android.media.MediaRoute2Info, int);
|
||||||
method public void setRouteVolume(@NonNull android.media.MediaRoute2Info, int);
|
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void startScan();
|
||||||
method public void startScan();
|
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void stopScan();
|
||||||
method public void stopScan();
|
method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void transfer(@NonNull android.media.MediaRouter2.RoutingController, @NonNull android.media.MediaRoute2Info);
|
||||||
method public void transfer(@NonNull android.media.MediaRouter2.RoutingController, @NonNull android.media.MediaRoute2Info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract static class MediaRouter2.RouteCallback {
|
public abstract static class MediaRouter2.RouteCallback {
|
||||||
|
|||||||
@@ -509,7 +509,7 @@ applications that come with the platform
|
|||||||
<!-- Permission required for CTS test - CtsAlarmManagerTestCases -->
|
<!-- Permission required for CTS test - CtsAlarmManagerTestCases -->
|
||||||
<permission name="android.permission.SCHEDULE_PRIORITIZED_ALARM" />
|
<permission name="android.permission.SCHEDULE_PRIORITIZED_ALARM" />
|
||||||
<!-- Permission required for CTS test - SystemMediaRouter2Test -->
|
<!-- Permission required for CTS test - SystemMediaRouter2Test -->
|
||||||
<permission name="android.permission.MODIFY_AUDIO_ROUTING"/>
|
<permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
|
||||||
<!-- Permission required for CTS test - CtsPermission5TestCases -->
|
<!-- Permission required for CTS test - CtsPermission5TestCases -->
|
||||||
<permission name="android.permission.RENOUNCE_PERMISSIONS" />
|
<permission name="android.permission.RENOUNCE_PERMISSIONS" />
|
||||||
<permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
|
<permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ interface IMediaRouterService {
|
|||||||
// MediaRouterService.java for readability.
|
// MediaRouterService.java for readability.
|
||||||
|
|
||||||
// Methods for MediaRouter2
|
// Methods for MediaRouter2
|
||||||
void checkModifyAudioRoutingPermission();
|
void enforceMediaContentControlPermission();
|
||||||
List<MediaRoute2Info> getSystemRoutes();
|
List<MediaRoute2Info> getSystemRoutes();
|
||||||
RoutingSessionInfo getSystemSessionInfo();
|
RoutingSessionInfo getSystemSessionInfo();
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package android.media;
|
|||||||
|
|
||||||
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
|
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.annotation.CallbackExecutor;
|
import android.annotation.CallbackExecutor;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -93,7 +94,7 @@ public final class MediaRouter2 {
|
|||||||
|
|
||||||
// TODO: Specify the fields that are only used (or not used) by system media router.
|
// TODO: Specify the fields that are only used (or not used) by system media router.
|
||||||
private final String mClientPackageName;
|
private final String mClientPackageName;
|
||||||
private final ManagerCallback mManagerCallback;
|
final ManagerCallback mManagerCallback;
|
||||||
|
|
||||||
private final String mPackageName;
|
private final String mPackageName;
|
||||||
|
|
||||||
@@ -164,13 +165,24 @@ public final class MediaRouter2 {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
|
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
|
||||||
@Nullable
|
@Nullable
|
||||||
public static MediaRouter2 getInstance(@NonNull Context context,
|
public static MediaRouter2 getInstance(@NonNull Context context,
|
||||||
@NonNull String clientPackageName) {
|
@NonNull String clientPackageName) {
|
||||||
Objects.requireNonNull(context, "context must not be null");
|
Objects.requireNonNull(context, "context must not be null");
|
||||||
Objects.requireNonNull(clientPackageName, "clientPackageName must not be null");
|
Objects.requireNonNull(clientPackageName, "clientPackageName must not be null");
|
||||||
|
|
||||||
|
// Note: Even though this check could be somehow bypassed, the other permission checks
|
||||||
|
// in system server will not allow MediaRouter2Manager to be registered.
|
||||||
|
IMediaRouterService serviceBinder = IMediaRouterService.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
|
||||||
|
try {
|
||||||
|
// SecurityException will be thrown if there's no permission.
|
||||||
|
serviceBinder.enforceMediaContentControlPermission();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Unable to check MEDIA_CONTENT_CONTROL permission.");
|
||||||
|
}
|
||||||
|
|
||||||
PackageManager pm = context.getPackageManager();
|
PackageManager pm = context.getPackageManager();
|
||||||
try {
|
try {
|
||||||
pm.getPackageInfo(clientPackageName, 0);
|
pm.getPackageInfo(clientPackageName, 0);
|
||||||
@@ -183,20 +195,13 @@ public final class MediaRouter2 {
|
|||||||
MediaRouter2 instance = sSystemMediaRouter2Map.get(clientPackageName);
|
MediaRouter2 instance = sSystemMediaRouter2Map.get(clientPackageName);
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
if (sManager == null) {
|
if (sManager == null) {
|
||||||
IMediaRouterService serviceBinder = IMediaRouterService.Stub.asInterface(
|
|
||||||
ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE));
|
|
||||||
try {
|
|
||||||
// MediaRouterService will throw a SecurityException if the caller
|
|
||||||
// doesn't have MODIFY_AUDIO_ROUTING permission.
|
|
||||||
serviceBinder.checkModifyAudioRoutingPermission();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
e.rethrowAsRuntimeException();
|
|
||||||
}
|
|
||||||
sManager = MediaRouter2Manager.getInstance(context.getApplicationContext());
|
sManager = MediaRouter2Manager.getInstance(context.getApplicationContext());
|
||||||
}
|
}
|
||||||
instance = new MediaRouter2(context, clientPackageName);
|
instance = new MediaRouter2(context, clientPackageName);
|
||||||
sSystemMediaRouter2Map.put(clientPackageName, instance);
|
sSystemMediaRouter2Map.put(clientPackageName, instance);
|
||||||
instance.registerManagerCallbackForSystemRouter();
|
// Using direct executor here, since MediaRouter2Manager also posts
|
||||||
|
// to the main handler.
|
||||||
|
sManager.registerCallback(Runnable::run, instance.mManagerCallback);
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
@@ -213,11 +218,15 @@ public final class MediaRouter2 {
|
|||||||
* Use {@link RouteCallback} to get the route related events.
|
* Use {@link RouteCallback} to get the route related events.
|
||||||
* <p>
|
* <p>
|
||||||
* Note that calling start/stopScan is applied to all system routers in the same process.
|
* Note that calling start/stopScan is applied to all system routers in the same process.
|
||||||
|
* <p>
|
||||||
|
* This will be no-op for non-system media routers.
|
||||||
*
|
*
|
||||||
* @see #stopScan()
|
* @see #stopScan()
|
||||||
|
* @see #getInstance(Context, String)
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
|
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
|
||||||
public void startScan() {
|
public void startScan() {
|
||||||
if (isSystemRouter()) {
|
if (isSystemRouter()) {
|
||||||
sManager.startScan();
|
sManager.startScan();
|
||||||
@@ -236,11 +245,15 @@ public final class MediaRouter2 {
|
|||||||
* Use {@link RouteCallback} to get the route related events.
|
* Use {@link RouteCallback} to get the route related events.
|
||||||
* <p>
|
* <p>
|
||||||
* Note that calling start/stopScan is applied to all system routers in the same process.
|
* Note that calling start/stopScan is applied to all system routers in the same process.
|
||||||
|
* <p>
|
||||||
|
* This will be no-op for non-system media routers.
|
||||||
*
|
*
|
||||||
* @see #startScan()
|
* @see #startScan()
|
||||||
|
* @see #getInstance(Context, String)
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
|
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
|
||||||
public void stopScan() {
|
public void stopScan() {
|
||||||
if (isSystemRouter()) {
|
if (isSystemRouter()) {
|
||||||
sManager.stopScan();
|
sManager.stopScan();
|
||||||
@@ -314,7 +327,8 @@ public final class MediaRouter2 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the client package name of the app which this media router controls.
|
* Gets the client package name of the app which this media router controls.
|
||||||
* This is only non-null when the router instance is created with the client package name.
|
* <p>
|
||||||
|
* This will return null for non-system media routers.
|
||||||
*
|
*
|
||||||
* @see #getInstance(Context, String)
|
* @see #getInstance(Context, String)
|
||||||
* @hide
|
* @hide
|
||||||
@@ -573,9 +587,25 @@ public final class MediaRouter2 {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Objects.requireNonNull(route, "route must not be null");
|
|
||||||
Log.v(TAG, "Transferring to route: " + route);
|
Log.v(TAG, "Transferring to route: " + route);
|
||||||
transfer(getCurrentController(), route);
|
|
||||||
|
boolean routeFound;
|
||||||
|
synchronized (mLock) {
|
||||||
|
// TODO: Check thread-safety
|
||||||
|
routeFound = mRoutes.containsKey(route.getId());
|
||||||
|
}
|
||||||
|
if (!routeFound) {
|
||||||
|
notifyTransferFailure(route);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RoutingController controller = getCurrentController();
|
||||||
|
if (controller.getRoutingSessionInfo().getTransferableRoutes().contains(route.getId())) {
|
||||||
|
controller.transferToRoute(route);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestCreateController(controller, route, MANAGER_REQUEST_ID_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -594,36 +624,20 @@ public final class MediaRouter2 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Transfers the media of a routing controller to the given route.
|
* Transfers the media of a routing controller to the given route.
|
||||||
|
* <p>
|
||||||
|
* This will be no-op for non-system media routers.
|
||||||
|
*
|
||||||
* @param controller a routing controller controlling media routing.
|
* @param controller a routing controller controlling media routing.
|
||||||
* @param route the route you want to transfer the media to.
|
* @param route the route you want to transfer the media to.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
|
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
|
||||||
public void transfer(@NonNull RoutingController controller, @NonNull MediaRoute2Info route) {
|
public void transfer(@NonNull RoutingController controller, @NonNull MediaRoute2Info route) {
|
||||||
if (isSystemRouter()) {
|
if (isSystemRouter()) {
|
||||||
sManager.transfer(controller.getRoutingSessionInfo(), route);
|
sManager.transfer(controller.getRoutingSessionInfo(), route);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Objects.requireNonNull(controller, "controller must not be null");
|
|
||||||
Objects.requireNonNull(route, "route must not be null");
|
|
||||||
|
|
||||||
boolean routeFound;
|
|
||||||
synchronized (mLock) {
|
|
||||||
// TODO: Check thread-safety
|
|
||||||
routeFound = mRoutes.containsKey(route.getId());
|
|
||||||
}
|
|
||||||
if (!routeFound) {
|
|
||||||
notifyTransferFailure(route);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (controller.getRoutingSessionInfo().getTransferableRoutes().contains(route.getId())) {
|
|
||||||
controller.transferToRoute(route);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
requestCreateController(controller, route, MANAGER_REQUEST_ID_NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void requestCreateController(@NonNull RoutingController controller,
|
void requestCreateController(@NonNull RoutingController controller,
|
||||||
@@ -687,9 +701,7 @@ public final class MediaRouter2 {
|
|||||||
/**
|
/**
|
||||||
* Gets a {@link RoutingController} whose ID is equal to the given ID.
|
* Gets a {@link RoutingController} whose ID is equal to the given ID.
|
||||||
* Returns {@code null} if there is no matching controller.
|
* Returns {@code null} if there is no matching controller.
|
||||||
* @hide
|
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public RoutingController getController(@NonNull String id) {
|
public RoutingController getController(@NonNull String id) {
|
||||||
Objects.requireNonNull(id, "id must not be null");
|
Objects.requireNonNull(id, "id must not be null");
|
||||||
@@ -739,14 +751,16 @@ public final class MediaRouter2 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests a volume change for the route asynchronously.
|
* Requests a volume change for the route asynchronously.
|
||||||
* <p>
|
|
||||||
* It may have no effect if the route is currently not selected.
|
* It may have no effect if the route is currently not selected.
|
||||||
* </p>
|
* <p>
|
||||||
|
* This will be no-op for non-system media routers.
|
||||||
*
|
*
|
||||||
* @param volume The new volume value between 0 and {@link MediaRoute2Info#getVolumeMax}.
|
* @param volume The new volume value between 0 and {@link MediaRoute2Info#getVolumeMax}.
|
||||||
|
* @see #getInstance(Context, String)
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
|
@RequiresPermission(Manifest.permission.MEDIA_CONTENT_CONTROL)
|
||||||
public void setRouteVolume(@NonNull MediaRoute2Info route, int volume) {
|
public void setRouteVolume(@NonNull MediaRoute2Info route, int volume) {
|
||||||
Objects.requireNonNull(route, "route must not be null");
|
Objects.requireNonNull(route, "route must not be null");
|
||||||
|
|
||||||
@@ -754,18 +768,7 @@ public final class MediaRouter2 {
|
|||||||
sManager.setRouteVolume(route, volume);
|
sManager.setRouteVolume(route, volume);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If this API needs to be public, use IMediaRouterService#setRouteVolumeWithRouter2()
|
||||||
MediaRouter2Stub stub;
|
|
||||||
synchronized (mLock) {
|
|
||||||
stub = mStub;
|
|
||||||
}
|
|
||||||
if (stub != null) {
|
|
||||||
try {
|
|
||||||
mMediaRouterService.setRouteVolumeWithRouter2(stub, route, volume);
|
|
||||||
} catch (RemoteException ex) {
|
|
||||||
Log.e(TAG, "Unable to set route volume.", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncRoutesOnHandler(List<MediaRoute2Info> currentRoutes,
|
void syncRoutesOnHandler(List<MediaRoute2Info> currentRoutes,
|
||||||
@@ -1039,15 +1042,6 @@ public final class MediaRouter2 {
|
|||||||
return mClientPackageName != null;
|
return mClientPackageName != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers {@link MediaRouter2Manager.Callback} for getting events.
|
|
||||||
* Should only used for system media routers.
|
|
||||||
*/
|
|
||||||
private void registerManagerCallbackForSystemRouter() {
|
|
||||||
// Using direct executor here, since MediaRouter2Manager also posts to the main handler.
|
|
||||||
sManager.registerCallback(Runnable::run, mManagerCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link RoutingSessionInfo} which has the client package name.
|
* Returns a {@link RoutingSessionInfo} which has the client package name.
|
||||||
* The client package name is set only when the given sessionInfo doesn't have it.
|
* The client package name is set only when the given sessionInfo doesn't have it.
|
||||||
@@ -1073,6 +1067,9 @@ public final class MediaRouter2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateAllRoutesFromManager() {
|
private void updateAllRoutesFromManager() {
|
||||||
|
if (!isSystemRouter()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
mRoutes.clear();
|
mRoutes.clear();
|
||||||
for (MediaRoute2Info route : sManager.getAllRoutes()) {
|
for (MediaRoute2Info route : sManager.getAllRoutes()) {
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that monitors and controls media routing of other apps.
|
* A class that monitors and controls media routing of other apps.
|
||||||
|
* {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} is required to use this class,
|
||||||
|
* or {@link SecurityException} will be thrown.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public final class MediaRouter2Manager {
|
public final class MediaRouter2Manager {
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ import static org.junit.Assert.assertNotNull;
|
|||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.UiAutomation;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.MediaRoute2Info;
|
import android.media.MediaRoute2Info;
|
||||||
import android.media.MediaRouter2;
|
import android.media.MediaRouter2;
|
||||||
@@ -87,6 +89,7 @@ public class MediaRouter2ManagerTest {
|
|||||||
private static final String TEST_NAME_UNKNOWN = "unknown";
|
private static final String TEST_NAME_UNKNOWN = "unknown";
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
private UiAutomation mUiAutomation;
|
||||||
private MediaRouter2Manager mManager;
|
private MediaRouter2Manager mManager;
|
||||||
private MediaRouter2 mRouter2;
|
private MediaRouter2 mRouter2;
|
||||||
private Executor mExecutor;
|
private Executor mExecutor;
|
||||||
@@ -110,6 +113,8 @@ public class MediaRouter2ManagerTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
mContext = InstrumentationRegistry.getTargetContext();
|
mContext = InstrumentationRegistry.getTargetContext();
|
||||||
|
mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
|
||||||
|
mUiAutomation.adoptShellPermissionIdentity(Manifest.permission.MEDIA_CONTENT_CONTROL);
|
||||||
mManager = MediaRouter2Manager.getInstance(mContext);
|
mManager = MediaRouter2Manager.getInstance(mContext);
|
||||||
mRouter2 = MediaRouter2.getInstance(mContext);
|
mRouter2 = MediaRouter2.getInstance(mContext);
|
||||||
// If we need to support thread pool executors, change this to thread pool executor.
|
// If we need to support thread pool executors, change this to thread pool executor.
|
||||||
@@ -129,6 +134,8 @@ public class MediaRouter2ManagerTest {
|
|||||||
instance.setProxy(null);
|
instance.setProxy(null);
|
||||||
instance.setSpy(null);
|
instance.setSpy(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mUiAutomation.dropShellPermissionIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -541,7 +541,7 @@
|
|||||||
<uses-permission android:name="android.permission.SCHEDULE_PRIORITIZED_ALARM" />
|
<uses-permission android:name="android.permission.SCHEDULE_PRIORITIZED_ALARM" />
|
||||||
|
|
||||||
<!-- Permission required for CTS test - SystemMediaRouter2Test -->
|
<!-- Permission required for CTS test - SystemMediaRouter2Test -->
|
||||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
|
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
|
||||||
|
|
||||||
<!-- Permission required for CTS test - CtsRotationResolverServiceDeviceTestCases -->
|
<!-- Permission required for CTS test - CtsRotationResolverServiceDeviceTestCases -->
|
||||||
<uses-permission android:name="android.permission.MANAGE_ROTATION_RESOLVER" />
|
<uses-permission android:name="android.permission.MANAGE_ROTATION_RESOLVER" />
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import static android.media.MediaRouter2Utils.getProviderId;
|
|||||||
|
|
||||||
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
|
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
@@ -142,16 +143,14 @@ class MediaRouter2ServiceImpl {
|
|||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public void checkModifyAudioRoutingPermission() {
|
public void enforceMediaContentControlPermission() {
|
||||||
final int pid = Binder.getCallingPid();
|
final int pid = Binder.getCallingPid();
|
||||||
final int uid = Binder.getCallingUid();
|
final int uid = Binder.getCallingUid();
|
||||||
final long token = Binder.clearCallingIdentity();
|
final long token = Binder.clearCallingIdentity();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (mContext.checkPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING, pid, uid)
|
mContext.enforcePermission(Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid,
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
"Must hold MEDIA_CONTENT_CONTROL permission.");
|
||||||
throw new SecurityException("Must hold the MODIFY_AUDIO_ROUTING permission.");
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(token);
|
Binder.restoreCallingIdentity(token);
|
||||||
}
|
}
|
||||||
@@ -890,6 +889,9 @@ class MediaRouter2ServiceImpl {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mContext.enforcePermission(Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid,
|
||||||
|
"Must hold MEDIA_CONTENT_CONTROL permission.");
|
||||||
|
|
||||||
UserRecord userRecord = getOrCreateUserRecordLocked(userId);
|
UserRecord userRecord = getOrCreateUserRecordLocked(userId);
|
||||||
managerRecord = new ManagerRecord(userRecord, manager, uid, pid, packageName);
|
managerRecord = new ManagerRecord(userRecord, manager, uid, pid, packageName);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -438,8 +438,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
|||||||
|
|
||||||
// Binder call
|
// Binder call
|
||||||
@Override
|
@Override
|
||||||
public void checkModifyAudioRoutingPermission() {
|
public void enforceMediaContentControlPermission() {
|
||||||
mService2.checkModifyAudioRoutingPermission();
|
mService2.enforceMediaContentControlPermission();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Binder call
|
// Binder call
|
||||||
|
|||||||
Reference in New Issue
Block a user