diff options
| author | 2020-02-14 11:44:45 +0900 | |
|---|---|---|
| committer | 2020-02-20 17:33:22 +0900 | |
| commit | 0fa60e880bf31d1644dc66fbd740db3e077edc2b (patch) | |
| tree | 8212f259de2f45616371f45aa2ef43020927e54f | |
| parent | 81a661fb49200eec924d6e02c5c62131a13bab9a (diff) | |
Add MediaRoute2ProviderService#notifyRequestFailed
Bug: 146616547
Test: atest mediaroutertest and CTS
Change-Id: I2b2b95bf0fec070ab24f51bba0c58221e5495460
15 files changed, 476 insertions, 176 deletions
diff --git a/api/current.txt b/api/current.txt index 71b27bc106d7..48dc27080fd6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -26873,21 +26873,27 @@ package android.media { ctor public MediaRoute2ProviderService(); method @NonNull public final java.util.List<android.media.RoutingSessionInfo> getAllSessionInfo(); method @Nullable public final android.media.RoutingSessionInfo getSessionInfo(@NonNull String); + method public final void notifyRequestFailed(long, int); method public final void notifyRoutes(@NonNull java.util.Collection<android.media.MediaRoute2Info>); method public final void notifySessionCreated(@NonNull android.media.RoutingSessionInfo, long); method public final void notifySessionCreationFailed(long); method public final void notifySessionReleased(@NonNull String); method public final void notifySessionUpdated(@NonNull android.media.RoutingSessionInfo); method @CallSuper @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent); - method public abstract void onCreateSession(@NonNull String, @NonNull String, long, @Nullable android.os.Bundle); - method public abstract void onDeselectRoute(@NonNull String, @NonNull String); + method public abstract void onCreateSession(long, @NonNull String, @NonNull String, @Nullable android.os.Bundle); + method public abstract void onDeselectRoute(long, @NonNull String, @NonNull String); method public void onDiscoveryPreferenceChanged(@NonNull android.media.RouteDiscoveryPreference); - method public abstract void onReleaseSession(@NonNull String); - method public abstract void onSelectRoute(@NonNull String, @NonNull String); - method public abstract void onSetRouteVolume(@NonNull String, int); - method public abstract void onSetSessionVolume(@NonNull String, int); - method public abstract void onTransferToRoute(@NonNull String, @NonNull String); - field public static final long REQUEST_ID_UNKNOWN = 0L; // 0x0L + method public abstract void onReleaseSession(long, @NonNull String); + method public abstract void onSelectRoute(long, @NonNull String, @NonNull String); + method public abstract void onSetRouteVolume(long, @NonNull String, int); + method public abstract void onSetSessionVolume(long, @NonNull String, int); + method public abstract void onTransferToRoute(long, @NonNull String, @NonNull String); + field public static final int REASON_INVALID_COMMAND = 4; // 0x4 + field public static final int REASON_NETWORK_ERROR = 2; // 0x2 + field public static final int REASON_REJECTED = 1; // 0x1 + field public static final int REASON_ROUTE_NOT_AVAILABLE = 3; // 0x3 + field public static final int REASON_UNKNOWN_ERROR = 0; // 0x0 + field public static final long REQUEST_ID_NONE = 0L; // 0x0L field public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService"; } diff --git a/media/java/android/media/IMediaRoute2ProviderService.aidl b/media/java/android/media/IMediaRoute2ProviderService.aidl index cd0def30fa03..6cd2547dcbcf 100644 --- a/media/java/android/media/IMediaRoute2ProviderService.aidl +++ b/media/java/android/media/IMediaRoute2ProviderService.aidl @@ -29,13 +29,13 @@ oneway interface IMediaRoute2ProviderService { // MediaRoute2ProviderService#MediaRoute2ProviderServiceStub for readability. void setCallback(IMediaRoute2ProviderServiceCallback callback); void updateDiscoveryPreference(in RouteDiscoveryPreference discoveryPreference); - void setRouteVolume(String routeId, int volume); + void setRouteVolume(String routeId, int volume, long requestId); void requestCreateSession(String packageName, String routeId, long requestId, in @nullable Bundle sessionHints); - void selectRoute(String sessionId, String routeId); - void deselectRoute(String sessionId, String routeId); - void transferToRoute(String sessionId, String routeId); - void setSessionVolume(String sessionId, int volume); - void releaseSession(String sessionId); + void selectRoute(String sessionId, String routeId, long requestId); + void deselectRoute(String sessionId, String routeId, long requestId); + void transferToRoute(String sessionId, String routeId, long requestId); + void setSessionVolume(String sessionId, int volume, long requestId); + void releaseSession(String sessionId, long requestId); } diff --git a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl index e35b0c4a1fdd..ab42d75bf14f 100644 --- a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl +++ b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl @@ -31,4 +31,5 @@ oneway interface IMediaRoute2ProviderServiceCallback { void notifySessionCreationFailed(long requestId); void notifySessionUpdated(in RoutingSessionInfo sessionInfo); void notifySessionReleased(in RoutingSessionInfo sessionInfo); + void notifyRequestFailed(long requestId, int reason); } diff --git a/media/java/android/media/IMediaRouter2Manager.aidl b/media/java/android/media/IMediaRouter2Manager.aidl index ffad6592e902..a2f9ee906c03 100644 --- a/media/java/android/media/IMediaRouter2Manager.aidl +++ b/media/java/android/media/IMediaRouter2Manager.aidl @@ -30,4 +30,5 @@ oneway interface IMediaRouter2Manager { void notifyRoutesAdded(in List<MediaRoute2Info> routes); void notifyRoutesRemoved(in List<MediaRoute2Info> routes); void notifyRoutesChanged(in List<MediaRoute2Info> routes); + void notifyRequestFailed(int requestId, int reason); } diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index cbec32386ed0..c7cb07d4ac1c 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -71,16 +71,17 @@ interface IMediaRouterService { void registerManager(IMediaRouter2Manager manager, String packageName); void unregisterManager(IMediaRouter2Manager manager); void setRouteVolumeWithManager(IMediaRouter2Manager manager, in MediaRoute2Info route, - int volume); + int volume, int requestId); void requestCreateSessionWithManager(IMediaRouter2Manager manager, String packageName, in @nullable MediaRoute2Info route, int requestId); void selectRouteWithManager(IMediaRouter2Manager manager, String sessionId, - in MediaRoute2Info route); + in MediaRoute2Info route, int requestId); void deselectRouteWithManager(IMediaRouter2Manager manager, String sessionId, - in MediaRoute2Info route); + in MediaRoute2Info route, int requestId); void transferToRouteWithManager(IMediaRouter2Manager manager, String sessionId, - in MediaRoute2Info route); - void setSessionVolumeWithManager(IMediaRouter2Manager manager, String sessionId, int volume); - void releaseSessionWithManager(IMediaRouter2Manager manager, String sessionId); + in MediaRoute2Info route, int requestId); + void setSessionVolumeWithManager(IMediaRouter2Manager manager, String sessionId, int volume, + int requestId); + void releaseSessionWithManager(IMediaRouter2Manager manager, String sessionId, int requestId); } diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java index 38233fd06745..aa0eda1fdbb1 100644 --- a/media/java/android/media/MediaRoute2ProviderService.java +++ b/media/java/android/media/MediaRoute2ProviderService.java @@ -19,6 +19,7 @@ package android.media; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.annotation.CallSuper; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; @@ -37,6 +38,8 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -51,7 +54,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * Media apps which use {@link MediaRouter2} can request to play their media on the routes. * </p><p> * When {@link MediaRouter2 media router} wants to play media on a route, - * {@link #onCreateSession(String, String, long, Bundle)} will be called to handle the request. + * {@link #onCreateSession(long, String, String, Bundle)} will be called to handle the request. * A session can be considered as a group of currently selected routes for each connection. * Create and manage the sessions by yourself, and notify the {@link RoutingSessionInfo * session infos} when there are any changes. @@ -61,6 +64,8 @@ import java.util.concurrent.atomic.AtomicBoolean; * a {@link MediaRouter2 media router} by an application. See * {@link #onDiscoveryPreferenceChanged(RouteDiscoveryPreference)} for the details. * </p> + * Use {@link #notifyRequestFailed(long, int)} to notify the failure with previously received + * request ID. */ public abstract class MediaRoute2ProviderService extends Service { private static final String TAG = "MR2ProviderService"; @@ -79,7 +84,53 @@ public abstract class MediaRoute2ProviderService extends Service { * * @see #notifySessionCreated(RoutingSessionInfo, long) */ - public static final long REQUEST_ID_UNKNOWN = 0; + public static final long REQUEST_ID_NONE = 0; + + /** + * The request has failed due to unknown reason. + * + * @see #notifyRequestFailed(long, int) + */ + public static final int REASON_UNKNOWN_ERROR = 0; + + /** + * The request has failed since this service rejected the request. + * + * @see #notifyRequestFailed(long, int) + */ + public static final int REASON_REJECTED = 1; + + /** + * The request has failed due to a network error. + * + * @see #notifyRequestFailed(long, int) + */ + public static final int REASON_NETWORK_ERROR = 2; + + /** + * The request has failed since the requested route is no longer available. + * + * @see #notifyRequestFailed(long, int) + */ + public static final int REASON_ROUTE_NOT_AVAILABLE = 3; + + /** + * The request has failed since the request is not valid. For example, selecting a route + * which is not selectable. + * + * @see #notifyRequestFailed(long, int) + */ + public static final int REASON_INVALID_COMMAND = 4; + + /** + * @hide + */ + @IntDef(prefix = "REASON_", value = { + REASON_UNKNOWN_ERROR, REASON_REJECTED, REASON_NETWORK_ERROR, REASON_ROUTE_NOT_AVAILABLE, + REASON_INVALID_COMMAND + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Reason {} private final Handler mHandler; private final Object mSessionLock = new Object(); @@ -116,20 +167,23 @@ public abstract class MediaRoute2ProviderService extends Service { /** * Called when a volume setting is requested on a route of the provider * + * @param requestId the id of this request * @param routeId the id of the route * @param volume the target volume - * @see MediaRoute2Info#getVolumeMax() + * @see MediaRoute2Info.Builder#setVolume(int) */ - public abstract void onSetRouteVolume(@NonNull String routeId, int volume); + public abstract void onSetRouteVolume(long requestId, @NonNull String routeId, int volume); /** * Called when {@link MediaRouter2.RoutingController#setVolume(int)} is called on * a routing session of the provider * + * @param requestId the id of this request * @param sessionId the id of the routing session * @param volume the target volume + * @see RoutingSessionInfo.Builder#setVolume(int) */ - public abstract void onSetSessionVolume(@NonNull String sessionId, int volume); + public abstract void onSetSessionVolume(long requestId, @NonNull String sessionId, int volume); /** * Gets information of the session with the given id. @@ -161,14 +215,15 @@ public abstract class MediaRoute2ProviderService extends Service { /** * Notifies clients of that the session is created and ready for use. * <p> - * If this session is created without any creation request, use {@link #REQUEST_ID_UNKNOWN} + * If this session is created without any creation request, use {@link #REQUEST_ID_NONE} * as the request ID. * * @param sessionInfo information of the new session. * The {@link RoutingSessionInfo#getId() id} of the session must be unique. * @param requestId id of the previous request to create this session provided in - * {@link #onCreateSession(String, String, long, Bundle)} - * @see #onCreateSession(String, String, long, Bundle) + * {@link #onCreateSession(long, String, String, Bundle)}. Can be + * {@link #REQUEST_ID_NONE} if this session is created without any request. + * @see #onCreateSession(long, String, String, Bundle) * @see #getSessionInfo(String) */ public final void notifySessionCreated(@NonNull RoutingSessionInfo sessionInfo, @@ -201,8 +256,8 @@ public abstract class MediaRoute2ProviderService extends Service { * Notifies clients of that the session could not be created. * * @param requestId id of the previous request to create the session provided in - * {@link #onCreateSession(String, String, long, Bundle)}. - * @see #onCreateSession(String, String, long, Bundle) + * {@link #onCreateSession(long, String, String, Bundle)}. + * @see #onCreateSession(long, String, String, Bundle) */ public final void notifySessionCreationFailed(long requestId) { if (mRemoteCallback == null) { @@ -246,7 +301,7 @@ public abstract class MediaRoute2ProviderService extends Service { * Notifies that the session is released. * * @param sessionId id of the released session. - * @see #onReleaseSession(String) + * @see #onReleaseSession(long, String) */ public final void notifySessionReleased(@NonNull String sessionId) { if (TextUtils.isEmpty(sessionId)) { @@ -273,6 +328,29 @@ public abstract class MediaRoute2ProviderService extends Service { } /** + * Notifies to the client that the request has failed. + * + * @param requestId the ID of the previous request + * @param reason the reason why the request has failed + * + * @see #REASON_UNKNOWN_ERROR + * @see #REASON_REJECTED + * @see #REASON_NETWORK_ERROR + * @see #REASON_ROUTE_NOT_AVAILABLE + * @see #REASON_INVALID_COMMAND + */ + public final void notifyRequestFailed(long requestId, @Reason int reason) { + if (mRemoteCallback == null) { + return; + } + try { + mRemoteCallback.notifyRequestFailed(requestId, reason); + } catch (RemoteException ex) { + Log.w(TAG, "Failed to notify that the request has failed."); + } + } + + /** * Called when the service receives a request to create a session. * <p> * You should create and maintain your own session and notifies the client of @@ -288,9 +366,9 @@ public abstract class MediaRoute2ProviderService extends Service { * If you can't create the session or want to reject the request, call * {@link #notifySessionCreationFailed(long)} with the given {@code requestId}. * + * @param requestId the id of this request * @param packageName the package name of the application that selected the route * @param routeId the id of the route initially being connected - * @param requestId the id of this session creation request * @param sessionHints an optional bundle of app-specific arguments sent by * {@link MediaRouter2}, or null if none. The contents of this bundle * may affect the result of session creation. @@ -299,8 +377,8 @@ public abstract class MediaRoute2ProviderService extends Service { * @see RoutingSessionInfo.Builder#addSelectedRoute(String) * @see RoutingSessionInfo.Builder#setControlHints(Bundle) */ - public abstract void onCreateSession(@NonNull String packageName, @NonNull String routeId, - long requestId, @Nullable Bundle sessionHints); + public abstract void onCreateSession(long requestId, @NonNull String packageName, + @NonNull String routeId, @Nullable Bundle sessionHints); /** * Called when the session should be released. A client of the session or system can request @@ -312,44 +390,48 @@ public abstract class MediaRoute2ProviderService extends Service { * Note: Calling {@link #notifySessionReleased(String)} will <em>NOT</em> trigger * this method to be called. * + * @param requestId the id of this request * @param sessionId id of the session being released. * @see #notifySessionReleased(String) * @see #getSessionInfo(String) */ - public abstract void onReleaseSession(@NonNull String sessionId); + public abstract void onReleaseSession(long requestId, @NonNull String sessionId); - //TODO: make a way to reject the request /** * Called when a client requests selecting a route for the session. * After the route is selected, call {@link #notifySessionUpdated(RoutingSessionInfo)} * to update session info. * + * @param requestId the id of this request * @param sessionId id of the session * @param routeId id of the route */ - public abstract void onSelectRoute(@NonNull String sessionId, @NonNull String routeId); + public abstract void onSelectRoute(long requestId, @NonNull String sessionId, + @NonNull String routeId); - //TODO: make a way to reject the request /** * Called when a client requests deselecting a route from the session. * After the route is deselected, call {@link #notifySessionUpdated(RoutingSessionInfo)} * to update session info. * + * @param requestId the id of this request * @param sessionId id of the session * @param routeId id of the route */ - public abstract void onDeselectRoute(@NonNull String sessionId, @NonNull String routeId); + public abstract void onDeselectRoute(long requestId, @NonNull String sessionId, + @NonNull String routeId); - //TODO: make a way to reject the request /** * Called when a client requests transferring a session to a route. * After the transfer is finished, call {@link #notifySessionUpdated(RoutingSessionInfo)} * to update session info. * + * @param requestId the id of this request * @param sessionId id of the session * @param routeId id of the route */ - public abstract void onTransferToRoute(@NonNull String sessionId, @NonNull String routeId); + public abstract void onTransferToRoute(long requestId, @NonNull String sessionId, + @NonNull String routeId); /** * Called when the {@link RouteDiscoveryPreference discovery preference} has changed. @@ -439,12 +521,12 @@ public abstract class MediaRoute2ProviderService extends Service { } @Override - public void setRouteVolume(String routeId, int volume) { + public void setRouteVolume(String routeId, int volume, long requestId) { if (!checkCallerisSystem()) { return; } mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetRouteVolume, - MediaRoute2ProviderService.this, routeId, volume)); + MediaRoute2ProviderService.this, requestId, routeId, volume)); } @Override @@ -454,12 +536,12 @@ public abstract class MediaRoute2ProviderService extends Service { return; } mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onCreateSession, - MediaRoute2ProviderService.this, packageName, routeId, requestId, + MediaRoute2ProviderService.this, requestId, packageName, routeId, requestCreateSession)); } @Override - public void selectRoute(@NonNull String sessionId, String routeId) { + public void selectRoute(String sessionId, String routeId, long requestId) { if (!checkCallerisSystem()) { return; } @@ -468,11 +550,11 @@ public abstract class MediaRoute2ProviderService extends Service { return; } mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelectRoute, - MediaRoute2ProviderService.this, sessionId, routeId)); + MediaRoute2ProviderService.this, requestId, sessionId, routeId)); } @Override - public void deselectRoute(@NonNull String sessionId, String routeId) { + public void deselectRoute(String sessionId, String routeId, long requestId) { if (!checkCallerisSystem()) { return; } @@ -481,11 +563,11 @@ public abstract class MediaRoute2ProviderService extends Service { return; } mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onDeselectRoute, - MediaRoute2ProviderService.this, sessionId, routeId)); + MediaRoute2ProviderService.this, requestId, sessionId, routeId)); } @Override - public void transferToRoute(@NonNull String sessionId, String routeId) { + public void transferToRoute(String sessionId, String routeId, long requestId) { if (!checkCallerisSystem()) { return; } @@ -494,20 +576,20 @@ public abstract class MediaRoute2ProviderService extends Service { return; } mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onTransferToRoute, - MediaRoute2ProviderService.this, sessionId, routeId)); + MediaRoute2ProviderService.this, requestId, sessionId, routeId)); } @Override - public void setSessionVolume(String sessionId, int volume) { + public void setSessionVolume(String sessionId, int volume, long requestId) { if (!checkCallerisSystem()) { return; } mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetSessionVolume, - MediaRoute2ProviderService.this, sessionId, volume)); + MediaRoute2ProviderService.this, requestId, sessionId, volume)); } @Override - public void releaseSession(@NonNull String sessionId) { + public void releaseSession(String sessionId, long requestId) { if (!checkCallerisSystem()) { return; } @@ -516,7 +598,7 @@ public abstract class MediaRoute2ProviderService extends Service { return; } mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onReleaseSession, - MediaRoute2ProviderService.this, sessionId)); + MediaRoute2ProviderService.this, requestId, sessionId)); } } } diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index 28bb4c192425..dfd7ceb140ea 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -817,7 +817,7 @@ public class MediaRouter2 { * @return An optional bundle of app-specific arguments to send to the provider, * or null if none. The contents of this bundle may affect the result of * controller creation. - * @see MediaRoute2ProviderService#onCreateSession(String, String, long, Bundle) + * @see MediaRoute2ProviderService#onCreateSession(long, String, String, Bundle) */ @Nullable Bundle onGetControllerHints(@NonNull MediaRoute2Info route); diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java index 636ee92f68a8..ff2c863aa7b0 100644 --- a/media/java/android/media/MediaRouter2Manager.java +++ b/media/java/android/media/MediaRouter2Manager.java @@ -337,7 +337,8 @@ public class MediaRouter2Manager { } if (client != null) { try { - mMediaRouterService.setRouteVolumeWithManager(client, route, volume); + int requestId = mNextRequestId.getAndIncrement(); + mMediaRouterService.setRouteVolumeWithManager(client, route, volume, requestId); } catch (RemoteException ex) { Log.e(TAG, "Unable to send control request.", ex); } @@ -368,8 +369,9 @@ public class MediaRouter2Manager { } if (client != null) { try { + int requestId = mNextRequestId.getAndIncrement(); mMediaRouterService.setSessionVolumeWithManager( - client, sessionInfo.getId(), volume); + client, sessionInfo.getId(), volume, requestId); } catch (RemoteException ex) { Log.e(TAG, "Unable to send control request.", ex); } @@ -443,6 +445,12 @@ public class MediaRouter2Manager { } } + void notifyRequestFailed(int reason) { + for (CallbackRecord record : mCallbackRecords) { + record.mExecutor.execute(() -> record.mCallback.onRequestFailed(reason)); + } + } + void updatePreferredFeatures(String packageName, List<String> preferredFeatures) { List<String> prevFeatures = mPreferredFeaturesMap.put(packageName, preferredFeatures); if ((prevFeatures == null && preferredFeatures.size() == 0) @@ -593,7 +601,9 @@ public class MediaRouter2Manager { } if (client != null) { try { - mMediaRouterService.selectRouteWithManager(mClient, getSessionId(), route); + int requestId = mNextRequestId.getAndIncrement(); + mMediaRouterService.selectRouteWithManager( + mClient, getSessionId(), route, requestId); } catch (RemoteException ex) { Log.e(TAG, "Unable to select route for session.", ex); } @@ -635,7 +645,9 @@ public class MediaRouter2Manager { } if (client != null) { try { - mMediaRouterService.deselectRouteWithManager(mClient, getSessionId(), route); + int requestId = mNextRequestId.getAndIncrement(); + mMediaRouterService.deselectRouteWithManager( + mClient, getSessionId(), route, requestId); } catch (RemoteException ex) { Log.e(TAG, "Unable to remove route from session.", ex); } @@ -678,7 +690,9 @@ public class MediaRouter2Manager { } if (client != null) { try { - mMediaRouterService.transferToRouteWithManager(mClient, getSessionId(), route); + int requestId = mNextRequestId.getAndIncrement(); + mMediaRouterService.transferToRouteWithManager( + mClient, getSessionId(), route, requestId); } catch (RemoteException ex) { Log.e(TAG, "Unable to transfer to route for session.", ex); } @@ -696,7 +710,9 @@ public class MediaRouter2Manager { } if (client != null) { try { - mMediaRouterService.releaseSessionWithManager(mClient, getSessionId()); + int requestId = mNextRequestId.getAndIncrement(); + mMediaRouterService.releaseSessionWithManager( + mClient, getSessionId(), requestId); } catch (RemoteException ex) { Log.e(TAG, "Unable to notify of controller release", ex); } @@ -783,6 +799,17 @@ public class MediaRouter2Manager { public void onPreferredFeaturesChanged(@NonNull String packageName, @NonNull List<String> preferredFeatures) {} + /** + * Called when a previous request has failed. + * + * @param reason the reason that the request has failed. Can be one of followings: + * {@link MediaRoute2ProviderService#REASON_UNKNOWN_ERROR}, + * {@link MediaRoute2ProviderService#REASON_REJECTED}, + * {@link MediaRoute2ProviderService#REASON_NETWORK_ERROR}, + * {@link MediaRoute2ProviderService#REASON_ROUTE_NOT_AVAILABLE}, + * {@link MediaRoute2ProviderService#REASON_INVALID_COMMAND}, + */ + public void onRequestFailed(int reason) {} } final class CallbackRecord { @@ -826,6 +853,13 @@ public class MediaRouter2Manager { } @Override + public void notifyRequestFailed(int requestId, int reason) { + // Note: requestId is not used. + mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyRequestFailed, + MediaRouter2Manager.this, reason)); + } + + @Override public void notifyPreferredFeaturesChanged(String packageName, List<String> features) { mHandler.sendMessage(obtainMessage(MediaRouter2Manager::updatePreferredFeatures, MediaRouter2Manager.this, packageName, features)); diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java index e80562b3fd1c..de941b4c7640 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java @@ -19,6 +19,8 @@ package com.android.mediaroutertest; import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO; import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED; import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE; +import static android.media.MediaRoute2ProviderService.REASON_REJECTED; +import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE; import static com.android.mediaroutertest.SampleMediaRoute2ProviderService.FEATURE_SAMPLE; import static com.android.mediaroutertest.SampleMediaRoute2ProviderService.FEATURE_SPECIAL; @@ -32,6 +34,7 @@ import static com.android.mediaroutertest.SampleMediaRoute2ProviderService.ROUTE import static com.android.mediaroutertest.SampleMediaRoute2ProviderService.VOLUME_MAX; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -69,6 +72,7 @@ import java.util.function.Predicate; @SmallTest public class MediaRouter2ManagerTest { private static final String TAG = "MediaRouter2ManagerTest"; + private static final int WAIT_TIME_MS = 2000; private static final int TIMEOUT_MS = 5000; private Context mContext; @@ -111,6 +115,11 @@ public class MediaRouter2ManagerTest { releaseAllSessions(); // unregister callbacks clearCallbacks(); + + SampleMediaRoute2ProviderService instance = SampleMediaRoute2ProviderService.getInstance(); + if (instance != null) { + instance.setProxy(null); + } } @Test @@ -398,6 +407,53 @@ public class MediaRouter2ManagerTest { } } + /** + * Tests that {@link android.media.MediaRoute2ProviderService#notifyRequestFailed(long, int)} + * should invoke the callback only when the right requestId is used. + */ + @Test + public void testOnRequestFailedCalledForProperRequestId() throws Exception { + Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL); + MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME); + + SampleMediaRoute2ProviderService instance = SampleMediaRoute2ProviderService.getInstance(); + assertNotNull(instance); + + final List<Long> requestIds = new ArrayList<>(); + final CountDownLatch onSetRouteVolumeLatch = new CountDownLatch(1); + instance.setProxy(new SampleMediaRoute2ProviderService.Proxy() { + @Override + public void onSetRouteVolume(String routeId, int volume, long requestId) { + requestIds.add(requestId); + onSetRouteVolumeLatch.countDown(); + } + }); + + addManagerCallback(new MediaRouter2Manager.Callback() {}); + mManager.setRouteVolume(volRoute, 0); + assertTrue(onSetRouteVolumeLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + assertFalse(requestIds.isEmpty()); + + final int failureReason = REASON_REJECTED; + final CountDownLatch onRequestFailedLatch = new CountDownLatch(1); + addManagerCallback(new MediaRouter2Manager.Callback() { + @Override + public void onRequestFailed(int reason) { + if (reason == failureReason) { + onRequestFailedLatch.countDown(); + } + } + }); + + final long invalidRequestId = REQUEST_ID_NONE; + instance.notifyRequestFailed(invalidRequestId, failureReason); + assertFalse(onRequestFailedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS)); + + final long validRequestId = requestIds.get(0); + instance.notifyRequestFailed(validRequestId, failureReason); + assertTrue(onRequestFailedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + } + @Test public void testVolumeHandling() throws Exception { Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL); diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java index 3faefdb148e1..9071c85cc8d2 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java @@ -75,6 +75,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService @GuardedBy("sLock") private static SampleMediaRoute2ProviderService sInstance; + private Proxy mProxy; private void initializeRoutes() { MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1) @@ -179,7 +180,13 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService } @Override - public void onSetRouteVolume(String routeId, int volume) { + public void onSetRouteVolume(long requestId, String routeId, int volume) { + Proxy proxy = mProxy; + if (proxy != null) { + proxy.onSetRouteVolume(routeId, volume, requestId); + return; + } + MediaRoute2Info route = mRoutes.get(routeId); if (route == null) { return; @@ -192,7 +199,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService } @Override - public void onSetSessionVolume(String sessionId, int volume) { + public void onSetSessionVolume(long requestId, String sessionId, int volume) { RoutingSessionInfo sessionInfo = getSessionInfo(sessionId); if (sessionInfo == null) { return; @@ -205,7 +212,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService } @Override - public void onCreateSession(String packageName, String routeId, long requestId, + public void onCreateSession(long requestId, String packageName, String routeId, @Nullable Bundle sessionHints) { MediaRoute2Info route = mRoutes.get(routeId); if (route == null || TextUtils.equals(ROUTE_ID3_SESSION_CREATION_FAILED, routeId)) { @@ -238,7 +245,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService } @Override - public void onReleaseSession(String sessionId) { + public void onReleaseSession(long requestId, String sessionId) { RoutingSessionInfo sessionInfo = getSessionInfo(sessionId); if (sessionInfo == null) { return; @@ -258,7 +265,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService } @Override - public void onSelectRoute(String sessionId, String routeId) { + public void onSelectRoute(long requestId, String sessionId, String routeId) { RoutingSessionInfo sessionInfo = getSessionInfo(sessionId); MediaRoute2Info route = mRoutes.get(routeId); if (route == null || sessionInfo == null) { @@ -280,7 +287,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService } @Override - public void onDeselectRoute(String sessionId, String routeId) { + public void onDeselectRoute(long requestId, String sessionId, String routeId) { RoutingSessionInfo sessionInfo = getSessionInfo(sessionId); MediaRoute2Info route = mRoutes.get(routeId); @@ -308,7 +315,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService } @Override - public void onTransferToRoute(String sessionId, String routeId) { + public void onTransferToRoute(long requestId, String sessionId, String routeId) { RoutingSessionInfo sessionInfo = getSessionInfo(sessionId); MediaRoute2Info route = mRoutes.get(routeId); @@ -347,10 +354,18 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService } String sessionId = mRouteIdToSessionId.get(routeId); - onDeselectRoute(sessionId, routeId); + onDeselectRoute(REQUEST_ID_NONE, sessionId, routeId); } void publishRoutes() { notifyRoutes(mRoutes.values()); } + + public void setProxy(@Nullable Proxy proxy) { + mProxy = proxy; + } + + public static class Proxy { + public void onSetRouteVolume(String routeId, int volume, long requestId) {} + } } diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java index 9b1824f7d7aa..f144405436f9 100644 --- a/services/core/java/com/android/server/media/MediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java @@ -53,15 +53,15 @@ abstract class MediaRoute2Provider { public abstract void requestCreateSession(String packageName, String routeId, long requestId, @Nullable Bundle sessionHints); - public abstract void releaseSession(String sessionId); + public abstract void releaseSession(String sessionId, long requestId); public abstract void updateDiscoveryPreference(RouteDiscoveryPreference discoveryPreference); - public abstract void selectRoute(String sessionId, String routeId); - public abstract void deselectRoute(String sessionId, String routeId); - public abstract void transferToRoute(String sessionId, String routeId); + public abstract void selectRoute(String sessionId, String routeId, long requestId); + public abstract void deselectRoute(String sessionId, String routeId, long requestId); + public abstract void transferToRoute(String sessionId, String routeId, long requestId); - public abstract void setRouteVolume(String routeId, int volume); - public abstract void setSessionVolume(String sessionId, int volume); + public abstract void setRouteVolume(String routeId, int volume, long requestId); + public abstract void setSessionVolume(String sessionId, int volume, long requestId); @NonNull public String getUniqueId() { @@ -116,5 +116,6 @@ abstract class MediaRoute2Provider { @NonNull RoutingSessionInfo sessionInfo); void onSessionReleased(@NonNull MediaRoute2Provider provider, @NonNull RoutingSessionInfo sessionInfo); + void onRequestFailed(@NonNull MediaRoute2Provider provider, long requestId, int reason); } } diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java index 60934e0cdfc6..e64776cc6e35 100644 --- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java +++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java @@ -87,9 +87,9 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider } @Override - public void releaseSession(String sessionId) { + public void releaseSession(String sessionId, long requestId) { if (mConnectionReady) { - mActiveConnection.releaseSession(sessionId); + mActiveConnection.releaseSession(sessionId, requestId); updateBinding(); } } @@ -103,38 +103,38 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider } @Override - public void selectRoute(String sessionId, String routeId) { + public void selectRoute(String sessionId, String routeId, long requestId) { if (mConnectionReady) { - mActiveConnection.selectRoute(sessionId, routeId); + mActiveConnection.selectRoute(sessionId, routeId, requestId); } } @Override - public void deselectRoute(String sessionId, String routeId) { + public void deselectRoute(String sessionId, String routeId, long requestId) { if (mConnectionReady) { - mActiveConnection.deselectRoute(sessionId, routeId); + mActiveConnection.deselectRoute(sessionId, routeId, requestId); } } @Override - public void transferToRoute(String sessionId, String routeId) { + public void transferToRoute(String sessionId, String routeId, long requestId) { if (mConnectionReady) { - mActiveConnection.transferToRoute(sessionId, routeId); + mActiveConnection.transferToRoute(sessionId, routeId, requestId); } } @Override - public void setRouteVolume(String routeId, int volume) { + public void setRouteVolume(String routeId, int volume, long requestId) { if (mConnectionReady) { - mActiveConnection.setRouteVolume(routeId, volume); + mActiveConnection.setRouteVolume(routeId, volume, requestId); updateBinding(); } } @Override - public void setSessionVolume(String sessionId, int volume) { + public void setSessionVolume(String sessionId, int volume, long requestId) { if (mConnectionReady) { - mActiveConnection.setSessionVolume(sessionId, volume); + mActiveConnection.setSessionVolume(sessionId, volume, requestId); updateBinding(); } } @@ -333,8 +333,8 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider return; } - if (requestId == MediaRoute2ProviderService.REQUEST_ID_UNKNOWN) { - Slog.w(TAG, "onSessionCreationFailed: Ignoring requestId REQUEST_ID_UNKNOWN"); + if (requestId == MediaRoute2ProviderService.REQUEST_ID_NONE) { + Slog.w(TAG, "onSessionCreationFailed: Ignoring requestId REQUEST_ID_NONE"); return; } @@ -406,6 +406,19 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider mCallback.onSessionReleased(this, sessionInfo); } + private void onRequestFailed(Connection connection, long requestId, int reason) { + if (mActiveConnection != connection) { + return; + } + + if (requestId == MediaRoute2ProviderService.REQUEST_ID_NONE) { + Slog.w(TAG, "onRequestFailed: Ignoring requestId REQUEST_ID_NONE"); + return; + } + + mCallback.onRequestFailed(this, requestId, reason); + } + private void disconnect() { if (mActiveConnection != null) { mConnectionReady = false; @@ -461,9 +474,9 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider } } - public void releaseSession(String sessionId) { + public void releaseSession(String sessionId, long requestId) { try { - mService.releaseSession(sessionId); + mService.releaseSession(sessionId, requestId); } catch (RemoteException ex) { Slog.e(TAG, "releaseSession: Failed to deliver request."); } @@ -477,41 +490,41 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider } } - public void selectRoute(String sessionId, String routeId) { + public void selectRoute(String sessionId, String routeId, long requestId) { try { - mService.selectRoute(sessionId, routeId); + mService.selectRoute(sessionId, routeId, requestId); } catch (RemoteException ex) { Slog.e(TAG, "selectRoute: Failed to deliver request.", ex); } } - public void deselectRoute(String sessionId, String routeId) { + public void deselectRoute(String sessionId, String routeId, long requestId) { try { - mService.deselectRoute(sessionId, routeId); + mService.deselectRoute(sessionId, routeId, requestId); } catch (RemoteException ex) { Slog.e(TAG, "deselectRoute: Failed to deliver request.", ex); } } - public void transferToRoute(String sessionId, String routeId) { + public void transferToRoute(String sessionId, String routeId, long requestId) { try { - mService.transferToRoute(sessionId, routeId); + mService.transferToRoute(sessionId, routeId, requestId); } catch (RemoteException ex) { Slog.e(TAG, "transferToRoute: Failed to deliver request.", ex); } } - public void setRouteVolume(String routeId, int volume) { + public void setRouteVolume(String routeId, int volume, long requestId) { try { - mService.setRouteVolume(routeId, volume); + mService.setRouteVolume(routeId, volume, requestId); } catch (RemoteException ex) { Slog.e(TAG, "setRouteVolume: Failed to deliver request.", ex); } } - public void setSessionVolume(String sessionId, int volume) { + public void setSessionVolume(String sessionId, int volume, long requestId) { try { - mService.setSessionVolume(sessionId, volume); + mService.setSessionVolume(sessionId, volume, requestId); } catch (RemoteException ex) { Slog.e(TAG, "setSessionVolume: Failed to deliver request.", ex); } @@ -541,6 +554,10 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider void postSessionReleased(RoutingSessionInfo sessionInfo) { mHandler.post(() -> onSessionReleased(Connection.this, sessionInfo)); } + + void postSessionReleased(long requestId, int reason) { + mHandler.post(() -> onRequestFailed(Connection.this, requestId, reason)); + } } private static final class ServiceCallbackStub extends @@ -594,5 +611,13 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider connection.postSessionReleased(sessionInfo); } } + + @Override + public void notifyRequestFailed(long requestId, int reason) { + Connection connection = mConnectionRef.get(); + if (connection != null) { + connection.postSessionReleased(requestId, reason); + } + } } } diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 358891675912..e78a35cd88a4 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -16,6 +16,7 @@ package com.android.server.media; +import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE; import static android.media.MediaRouter2Utils.getOriginalId; import static android.media.MediaRouter2Utils.getProviderId; @@ -30,7 +31,6 @@ import android.media.IMediaRouter2; import android.media.IMediaRouter2Manager; import android.media.MediaRoute2Info; import android.media.MediaRoute2ProviderInfo; -import android.media.MediaRoute2ProviderService; import android.media.RouteDiscoveryPreference; import android.media.RoutingSessionInfo; import android.os.Binder; @@ -70,6 +70,12 @@ class MediaRouter2ServiceImpl { private static final String TAG = "MR2ServiceImpl"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + /** + * TODO: Change this with the real request ID from MediaRouter2 when + * MediaRouter2 needs to get notified for the failures. + */ + private static final long DUMMY_REQUEST_ID = -1; + private final Context mContext; private final Object mLock = new Object(); final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1); @@ -365,14 +371,14 @@ class MediaRouter2ServiceImpl { } public void setRouteVolumeWithManager(IMediaRouter2Manager manager, - MediaRoute2Info route, int volume) { + MediaRoute2Info route, int volume, int requestId) { Objects.requireNonNull(manager, "manager must not be null"); Objects.requireNonNull(route, "route must not be null"); final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - setRouteVolumeWithManagerLocked(manager, route, volume); + setRouteVolumeWithManagerLocked(manager, route, volume, requestId); } } finally { Binder.restoreCallingIdentity(token); @@ -397,7 +403,7 @@ class MediaRouter2ServiceImpl { } public void selectRouteWithManager(IMediaRouter2Manager manager, String uniqueSessionId, - MediaRoute2Info route) { + MediaRoute2Info route, int requestId) { Objects.requireNonNull(manager, "manager must not be null"); if (TextUtils.isEmpty(uniqueSessionId)) { throw new IllegalArgumentException("uniqueSessionId must not be empty"); @@ -407,7 +413,7 @@ class MediaRouter2ServiceImpl { final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - selectRouteWithManagerLocked(manager, uniqueSessionId, route); + selectRouteWithManagerLocked(manager, uniqueSessionId, route, requestId); } } finally { Binder.restoreCallingIdentity(token); @@ -415,7 +421,7 @@ class MediaRouter2ServiceImpl { } public void deselectRouteWithManager(IMediaRouter2Manager manager, String uniqueSessionId, - MediaRoute2Info route) { + MediaRoute2Info route, int requestId) { Objects.requireNonNull(manager, "manager must not be null"); if (TextUtils.isEmpty(uniqueSessionId)) { throw new IllegalArgumentException("uniqueSessionId must not be empty"); @@ -425,7 +431,7 @@ class MediaRouter2ServiceImpl { final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - deselectRouteWithManagerLocked(manager, uniqueSessionId, route); + deselectRouteWithManagerLocked(manager, uniqueSessionId, route, requestId); } } finally { Binder.restoreCallingIdentity(token); @@ -433,7 +439,7 @@ class MediaRouter2ServiceImpl { } public void transferToRouteWithManager(IMediaRouter2Manager manager, String uniqueSessionId, - MediaRoute2Info route) { + MediaRoute2Info route, int requestId) { Objects.requireNonNull(manager, "manager must not be null"); if (TextUtils.isEmpty(uniqueSessionId)) { throw new IllegalArgumentException("uniqueSessionId must not be empty"); @@ -443,7 +449,7 @@ class MediaRouter2ServiceImpl { final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - transferToRouteWithManagerLocked(manager, uniqueSessionId, route); + transferToRouteWithManagerLocked(manager, uniqueSessionId, route, requestId); } } finally { Binder.restoreCallingIdentity(token); @@ -451,7 +457,7 @@ class MediaRouter2ServiceImpl { } public void setSessionVolumeWithManager(IMediaRouter2Manager manager, - String uniqueSessionId, int volume) { + String uniqueSessionId, int volume, int requestId) { Objects.requireNonNull(manager, "manager must not be null"); if (TextUtils.isEmpty(uniqueSessionId)) { throw new IllegalArgumentException("uniqueSessionId must not be empty"); @@ -460,14 +466,15 @@ class MediaRouter2ServiceImpl { final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - setSessionVolumeWithManagerLocked(manager, uniqueSessionId, volume); + setSessionVolumeWithManagerLocked(manager, uniqueSessionId, volume, requestId); } } finally { Binder.restoreCallingIdentity(token); } } - public void releaseSessionWithManager(IMediaRouter2Manager manager, String uniqueSessionId) { + public void releaseSessionWithManager(IMediaRouter2Manager manager, String uniqueSessionId, + int requestId) { Objects.requireNonNull(manager, "manager must not be null"); if (TextUtils.isEmpty(uniqueSessionId)) { throw new IllegalArgumentException("uniqueSessionId must not be empty"); @@ -476,7 +483,7 @@ class MediaRouter2ServiceImpl { final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - releaseSessionWithManagerLocked(manager, uniqueSessionId); + releaseSessionWithManagerLocked(manager, uniqueSessionId, requestId); } } finally { Binder.restoreCallingIdentity(token); @@ -572,7 +579,7 @@ class MediaRouter2ServiceImpl { obtainMessage(UserHandler::notifyPreferredFeaturesChangedToManagers, routerRecord.mUserRecord.mHandler, routerRecord)); routerRecord.mUserRecord.mHandler.sendMessage( - obtainMessage(UserHandler::updateDiscoveryPreference, + obtainMessage(UserHandler::updateDiscoveryPreferenceOnHandler, routerRecord.mUserRecord.mHandler)); } @@ -584,7 +591,7 @@ class MediaRouter2ServiceImpl { if (routerRecord != null) { routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::setRouteVolumeOnHandler, - routerRecord.mUserRecord.mHandler, route, volume)); + routerRecord.mUserRecord.mHandler, route, volume, DUMMY_REQUEST_ID)); } } @@ -615,7 +622,8 @@ class MediaRouter2ServiceImpl { routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::selectRouteOnHandler, - routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route)); + routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route, + DUMMY_REQUEST_ID)); } private void deselectRouteWithRouter2Locked(@NonNull IMediaRouter2 router, @@ -629,7 +637,8 @@ class MediaRouter2ServiceImpl { routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::deselectRouteOnHandler, - routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route)); + routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route, + DUMMY_REQUEST_ID)); } private void transferToRouteWithRouter2Locked(@NonNull IMediaRouter2 router, @@ -643,7 +652,8 @@ class MediaRouter2ServiceImpl { routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::transferToRouteOnHandler, - routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route)); + routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route, + DUMMY_REQUEST_ID)); } private void setSessionVolumeWithRouter2Locked(@NonNull IMediaRouter2 router, @@ -657,7 +667,8 @@ class MediaRouter2ServiceImpl { routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::setSessionVolumeOnHandler, - routerRecord.mUserRecord.mHandler, uniqueSessionId, volume)); + routerRecord.mUserRecord.mHandler, uniqueSessionId, volume, + DUMMY_REQUEST_ID)); } private void releaseSessionWithRouter2Locked(@NonNull IMediaRouter2 router, @@ -671,7 +682,8 @@ class MediaRouter2ServiceImpl { routerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::releaseSessionOnHandler, - routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId)); + routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, + DUMMY_REQUEST_ID)); } //////////////////////////////////////////////////////////// @@ -744,16 +756,18 @@ class MediaRouter2ServiceImpl { } private void setRouteVolumeWithManagerLocked(@NonNull IMediaRouter2Manager manager, - @NonNull MediaRoute2Info route, int volume) { + @NonNull MediaRoute2Info route, int volume, int requestId) { final IBinder binder = manager.asBinder(); ManagerRecord managerRecord = mAllManagerRecords.get(binder); if (managerRecord == null) { return; } + + long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId); managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::setRouteVolumeOnHandler, - managerRecord.mUserRecord.mHandler, route, volume)); + managerRecord.mUserRecord.mHandler, route, volume, uniqueRequestId)); } private void requestCreateSessionWithManagerLocked(@NonNull IMediaRouter2Manager manager, @@ -778,7 +792,7 @@ class MediaRouter2ServiceImpl { } private void selectRouteWithManagerLocked(@NonNull IMediaRouter2Manager manager, - @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) { + @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, int requestId) { final IBinder binder = manager.asBinder(); ManagerRecord managerRecord = mAllManagerRecords.get(binder); @@ -790,13 +804,15 @@ class MediaRouter2ServiceImpl { RouterRecord routerRecord = managerRecord.mUserRecord.mHandler .findRouterforSessionLocked(uniqueSessionId); + long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId); managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::selectRouteOnHandler, - managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route)); + managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route, + uniqueRequestId)); } private void deselectRouteWithManagerLocked(@NonNull IMediaRouter2Manager manager, - @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) { + @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, int requestId) { final IBinder binder = manager.asBinder(); ManagerRecord managerRecord = mAllManagerRecords.get(binder); @@ -808,13 +824,15 @@ class MediaRouter2ServiceImpl { RouterRecord routerRecord = managerRecord.mUserRecord.mHandler .findRouterforSessionLocked(uniqueSessionId); + long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId); managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::deselectRouteOnHandler, - managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route)); + managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route, + uniqueRequestId)); } private void transferToRouteWithManagerLocked(@NonNull IMediaRouter2Manager manager, - @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) { + @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, int requestId) { final IBinder binder = manager.asBinder(); ManagerRecord managerRecord = mAllManagerRecords.get(binder); @@ -826,13 +844,15 @@ class MediaRouter2ServiceImpl { RouterRecord routerRecord = managerRecord.mUserRecord.mHandler .findRouterforSessionLocked(uniqueSessionId); + long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId); managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::transferToRouteOnHandler, - managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route)); + managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route, + uniqueRequestId)); } private void setSessionVolumeWithManagerLocked(@NonNull IMediaRouter2Manager manager, - @NonNull String uniqueSessionId, int volume) { + @NonNull String uniqueSessionId, int volume, int requestId) { final IBinder binder = manager.asBinder(); ManagerRecord managerRecord = mAllManagerRecords.get(binder); @@ -840,13 +860,15 @@ class MediaRouter2ServiceImpl { return; } + long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId); managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::setSessionVolumeOnHandler, - managerRecord.mUserRecord.mHandler, uniqueSessionId, volume)); + managerRecord.mUserRecord.mHandler, uniqueSessionId, volume, + uniqueRequestId)); } private void releaseSessionWithManagerLocked(@NonNull IMediaRouter2Manager manager, - @NonNull String uniqueSessionId) { + @NonNull String uniqueSessionId, int requestId) { final IBinder binder = manager.asBinder(); ManagerRecord managerRecord = mAllManagerRecords.get(binder); @@ -856,10 +878,15 @@ class MediaRouter2ServiceImpl { RouterRecord routerRecord = managerRecord.mUserRecord.mHandler .findRouterforSessionLocked(uniqueSessionId); + if (routerRecord == null) { + return; + } + long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId); managerRecord.mUserRecord.mHandler.sendMessage( obtainMessage(UserHandler::releaseSessionOnHandler, - managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId)); + managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, + uniqueRequestId)); } //////////////////////////////////////////////////////////// @@ -1100,6 +1127,13 @@ class MediaRouter2ServiceImpl { this, provider, sessionInfo)); } + @Override + public void onRequestFailed(@NonNull MediaRoute2Provider provider, long requestId, + int reason) { + sendMessage(PooledLambda.obtainMessage(UserHandler::onRequestFailedOnHandler, + this, provider, requestId, reason)); + } + @Nullable public RouterRecord findRouterforSessionLocked(@NonNull String uniqueSessionId) { return mSessionToRouterMap.get(uniqueSessionId); @@ -1195,7 +1229,7 @@ class MediaRouter2ServiceImpl { if (provider == null) { Slog.w(TAG, "Ignoring session creation request since no provider found for" + " given route=" + route); - notifySessionCreationFailed(routerRecord, toOriginalRequestId(requestId)); + notifySessionCreationFailedToRouter(routerRecord, toOriginalRequestId(requestId)); return; } @@ -1210,7 +1244,7 @@ class MediaRouter2ServiceImpl { // routerRecord can be null if the session is system's. private void selectRouteOnHandler(@Nullable RouterRecord routerRecord, - @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) { + @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, long requestId) { if (!checkArgumentsForSessionControl(routerRecord, uniqueSessionId, route, "selecting")) { return; @@ -1222,12 +1256,12 @@ class MediaRouter2ServiceImpl { if (provider == null) { return; } - provider.selectRoute(getOriginalId(uniqueSessionId), route.getOriginalId()); + provider.selectRoute(getOriginalId(uniqueSessionId), route.getOriginalId(), requestId); } // routerRecord can be null if the session is system's. private void deselectRouteOnHandler(@Nullable RouterRecord routerRecord, - @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) { + @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, long requestId) { if (!checkArgumentsForSessionControl(routerRecord, uniqueSessionId, route, "deselecting")) { return; @@ -1239,12 +1273,13 @@ class MediaRouter2ServiceImpl { if (provider == null) { return; } - provider.deselectRoute(getOriginalId(uniqueSessionId), route.getOriginalId()); + provider.deselectRoute(getOriginalId(uniqueSessionId), route.getOriginalId(), + requestId); } // routerRecord can be null if the session is system's. private void transferToRouteOnHandler(@Nullable RouterRecord routerRecord, - @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) { + @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, long requestId) { if (!checkArgumentsForSessionControl(routerRecord, uniqueSessionId, route, "transferring to")) { return; @@ -1256,7 +1291,8 @@ class MediaRouter2ServiceImpl { if (provider == null) { return; } - provider.transferToRoute(getOriginalId(uniqueSessionId), route.getOriginalId()); + provider.transferToRoute(getOriginalId(uniqueSessionId), route.getOriginalId(), + requestId); } private boolean checkArgumentsForSessionControl(@Nullable RouterRecord routerRecord, @@ -1299,7 +1335,7 @@ class MediaRouter2ServiceImpl { } private void releaseSessionOnHandler(@NonNull RouterRecord routerRecord, - @NonNull String uniqueSessionId) { + @NonNull String uniqueSessionId, long uniqueRequestId) { final RouterRecord matchingRecord = mSessionToRouterMap.get(uniqueSessionId); if (matchingRecord != routerRecord) { Slog.w(TAG, "Ignoring releasing session from non-matching router." @@ -1329,14 +1365,14 @@ class MediaRouter2ServiceImpl { return; } - provider.releaseSession(sessionId); + provider.releaseSession(sessionId, uniqueRequestId); } private void onSessionCreatedOnHandler(@NonNull MediaRoute2Provider provider, @NonNull RoutingSessionInfo sessionInfo, long requestId) { notifySessionCreatedToManagers(getManagers(), sessionInfo); - if (requestId == MediaRoute2ProviderService.REQUEST_ID_UNKNOWN) { + if (requestId == REQUEST_ID_NONE) { // The session is created without any matching request. return; } @@ -1362,7 +1398,7 @@ class MediaRouter2ServiceImpl { if (sessionInfo == null) { // Failed - notifySessionCreationFailed(matchingRequest.mRouterRecord, + notifySessionCreationFailedToRouter(matchingRequest.mRouterRecord, toOriginalRequestId(requestId)); return; } @@ -1374,13 +1410,13 @@ class MediaRouter2ServiceImpl { Slog.w(TAG, "Created session doesn't match the original request." + " originalRouteId=" + originalRouteId + ", requestId=" + requestId + ", sessionInfo=" + sessionInfo); - notifySessionCreationFailed(matchingRequest.mRouterRecord, + notifySessionCreationFailedToRouter(matchingRequest.mRouterRecord, toOriginalRequestId(requestId)); return; } // Succeeded - notifySessionCreated(matchingRequest.mRouterRecord, + notifySessionCreatedToRouter(matchingRequest.mRouterRecord, sessionInfo, toOriginalRequestId(requestId)); mSessionToRouterMap.put(sessionInfo.getId(), routerRecord); } @@ -1405,7 +1441,7 @@ class MediaRouter2ServiceImpl { } mSessionCreationRequests.remove(matchingRequest); - notifySessionCreationFailed(matchingRequest.mRouterRecord, + notifySessionCreationFailedToRouter(matchingRequest.mRouterRecord, toOriginalRequestId(requestId)); } @@ -1429,7 +1465,7 @@ class MediaRouter2ServiceImpl { Slog.w(TAG, "No matching router found for session=" + sessionInfo); return; } - notifySessionInfoChanged(routerRecord, sessionInfo); + notifySessionInfoChangedToRouter(routerRecord, sessionInfo); } private void onSessionReleasedOnHandler(@NonNull MediaRoute2Provider provider, @@ -1442,10 +1478,38 @@ class MediaRouter2ServiceImpl { Slog.w(TAG, "No matching router found for session=" + sessionInfo); return; } - notifySessionReleased(routerRecord, sessionInfo); + notifySessionReleasedToRouter(routerRecord, sessionInfo); } - private void notifySessionCreated(@NonNull RouterRecord routerRecord, + private void onRequestFailedOnHandler(@NonNull MediaRoute2Provider provider, + long requestId, int reason) { + final int managerId = toRouterOrManagerId(requestId); + + MediaRouter2ServiceImpl service = mServiceRef.get(); + if (service == null) { + return; + } + + ManagerRecord managerToNotifyFailure = null; + synchronized (service.mLock) { + for (ManagerRecord manager : mUserRecord.mManagerRecords) { + if (manager.mManagerId == managerId) { + managerToNotifyFailure = manager; + break; + } + } + } + + if (managerToNotifyFailure == null) { + Slog.w(TAG, "No matching managerRecord found for managerId=" + managerId); + return; + } + + notifyRequestFailedToManager( + managerToNotifyFailure.mManager, toOriginalRequestId(requestId), reason); + } + + private void notifySessionCreatedToRouter(@NonNull RouterRecord routerRecord, @NonNull RoutingSessionInfo sessionInfo, int requestId) { try { routerRecord.mRouter.notifySessionCreated(sessionInfo, requestId); @@ -1455,7 +1519,7 @@ class MediaRouter2ServiceImpl { } } - private void notifySessionCreationFailed(@NonNull RouterRecord routerRecord, + private void notifySessionCreationFailedToRouter(@NonNull RouterRecord routerRecord, int requestId) { try { routerRecord.mRouter.notifySessionCreated(/* sessionInfo= */ null, requestId); @@ -1465,7 +1529,7 @@ class MediaRouter2ServiceImpl { } } - private void notifySessionInfoChanged(@NonNull RouterRecord routerRecord, + private void notifySessionInfoChangedToRouter(@NonNull RouterRecord routerRecord, @NonNull RoutingSessionInfo sessionInfo) { try { routerRecord.mRouter.notifySessionInfoChanged(sessionInfo); @@ -1475,7 +1539,7 @@ class MediaRouter2ServiceImpl { } } - private void notifySessionReleased(@NonNull RouterRecord routerRecord, + private void notifySessionReleasedToRouter(@NonNull RouterRecord routerRecord, @NonNull RoutingSessionInfo sessionInfo) { try { routerRecord.mRouter.notifySessionReleased(sessionInfo); @@ -1485,21 +1549,23 @@ class MediaRouter2ServiceImpl { } } - private void setRouteVolumeOnHandler(@NonNull MediaRoute2Info route, int volume) { + private void setRouteVolumeOnHandler(@NonNull MediaRoute2Info route, int volume, + long requestId) { final MediaRoute2Provider provider = findProvider(route.getProviderId()); if (provider != null) { - provider.setRouteVolume(route.getOriginalId(), volume); + provider.setRouteVolume(route.getOriginalId(), volume, requestId); } } - private void setSessionVolumeOnHandler(@NonNull String uniqueSessionId, int volume) { + private void setSessionVolumeOnHandler(@NonNull String uniqueSessionId, int volume, + long requestId) { final MediaRoute2Provider provider = findProvider(getProviderId(uniqueSessionId)); if (provider == null) { Slog.w(TAG, "setSessionVolume: couldn't find provider for session " + "id=" + uniqueSessionId); return; } - provider.setSessionVolume(getOriginalId(uniqueSessionId), volume); + provider.setSessionVolume(getOriginalId(uniqueSessionId), volume, requestId); } private List<IMediaRouter2> getRouters() { @@ -1683,7 +1749,17 @@ class MediaRouter2ServiceImpl { } } - private void updateDiscoveryPreference() { + private void notifyRequestFailedToManager(@NonNull IMediaRouter2Manager manager, + int requestId, int reason) { + try { + manager.notifyRequestFailed(requestId, reason); + } catch (RemoteException ex) { + Slog.w(TAG, "Failed to notify manager of the request failure." + + " Manager probably died.", ex); + } + } + + private void updateDiscoveryPreferenceOnHandler() { MediaRouter2ServiceImpl service = mServiceRef.get(); if (service == null) { return; diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index 580fc5250e35..a13ee1058a26 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -543,8 +543,8 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override public void setRouteVolumeWithManager(IMediaRouter2Manager manager, - MediaRoute2Info route, int volume) { - mService2.setRouteVolumeWithManager(manager, route, volume); + MediaRoute2Info route, int volume, int requestId) { + mService2.setRouteVolumeWithManager(manager, route, volume, requestId); } // Binder call @@ -557,35 +557,36 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override public void selectRouteWithManager(IMediaRouter2Manager manager, String sessionId, - MediaRoute2Info route) { - mService2.selectRouteWithManager(manager, sessionId, route); + MediaRoute2Info route, int requestId) { + mService2.selectRouteWithManager(manager, sessionId, route, requestId); } // Binder call @Override public void deselectRouteWithManager(IMediaRouter2Manager manager, String sessionId, - MediaRoute2Info route) { - mService2.deselectRouteWithManager(manager, sessionId, route); + MediaRoute2Info route, int requestId) { + mService2.deselectRouteWithManager(manager, sessionId, route, requestId); } // Binder call @Override public void transferToRouteWithManager(IMediaRouter2Manager manager, String sessionId, - MediaRoute2Info route) { - mService2.transferToRouteWithManager(manager, sessionId, route); + MediaRoute2Info route, int requestId) { + mService2.transferToRouteWithManager(manager, sessionId, route, requestId); } // Binder call @Override public void setSessionVolumeWithManager(IMediaRouter2Manager manager, - String sessionId, int volume) { - mService2.setSessionVolumeWithManager(manager, sessionId, volume); + String sessionId, int volume, int requestId) { + mService2.setSessionVolumeWithManager(manager, sessionId, volume, requestId); } // Binder call @Override - public void releaseSessionWithManager(IMediaRouter2Manager manager, String sessionId) { - mService2.releaseSessionWithManager(manager, sessionId); + public void releaseSessionWithManager(IMediaRouter2Manager manager, String sessionId, + int requestId) { + mService2.releaseSessionWithManager(manager, sessionId, requestId); } void restoreBluetoothA2dp() { diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index f7e1398a2bd3..ce72a8a5c807 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -130,26 +130,27 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } @Override - public void releaseSession(String sessionId) { + public void releaseSession(String sessionId, long requestId) { // Do nothing } + @Override public void updateDiscoveryPreference(RouteDiscoveryPreference discoveryPreference) { // Do nothing } @Override - public void selectRoute(String sessionId, String routeId) { + public void selectRoute(String sessionId, String routeId, long requestId) { // Do nothing since we don't support multiple BT yet. } @Override - public void deselectRoute(String sessionId, String routeId) { + public void deselectRoute(String sessionId, String routeId, long requestId) { // Do nothing since we don't support multiple BT yet. } @Override - public void transferToRoute(String sessionId, String routeId) { + public void transferToRoute(String sessionId, String routeId, long requestId) { if (TextUtils.equals(routeId, mDefaultRoute.getId())) { mBtRouteProvider.transferTo(null); } else { @@ -158,7 +159,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } @Override - public void setRouteVolume(String routeId, int volume) { + public void setRouteVolume(String routeId, int volume, long requestId) { if (!TextUtils.equals(routeId, mSelectedRouteId)) { return; } @@ -166,7 +167,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } @Override - public void setSessionVolume(String sessionId, int volume) { + public void setSessionVolume(String sessionId, int volume, long requestId) { // Do nothing since we don't support grouping volume yet. } |