Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3446559 authored by Kyunglyul Hyun's avatar Kyunglyul Hyun
Browse files

Fix MediaRoute2ProviderService TODOs

This CL ignores requests that contain unknown session IDs and
make sure sequence of binder calls are aligned with notifySession
Created/Updated/Released.

Bug: 157873546
Bug: 157873487
Test: Run CTS and atest mediarouter test
Change-Id: Ie31e2fca8160093cf54886180e67d40865a35d6d
parent 5c8f3b20
Loading
Loading
Loading
Loading
+101 −71
Original line number Diff line number Diff line
@@ -137,7 +137,7 @@ public abstract class MediaRoute2ProviderService extends Service {
    private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
    private MediaRoute2ProviderServiceStub mStub;
    private IMediaRoute2ProviderServiceCallback mRemoteCallback;
    private MediaRoute2ProviderInfo mProviderInfo;
    private volatile MediaRoute2ProviderInfo mProviderInfo;

    @GuardedBy("mSessionLock")
    private ArrayMap<String, RoutingSessionInfo> mSessionInfo = new ArrayMap<>();
@@ -167,8 +167,8 @@ 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 requestId the ID of this request
     * @param routeId the ID of the route
     * @param volume the target volume
     * @see MediaRoute2Info.Builder#setVolume(int)
     */
@@ -178,8 +178,8 @@ public abstract class MediaRoute2ProviderService extends Service {
     * 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 requestId the ID of this request
     * @param sessionId the ID of the routing session
     * @param volume the target volume
     * @see RoutingSessionInfo.Builder#setVolume(int)
     */
@@ -188,7 +188,7 @@ public abstract class MediaRoute2ProviderService extends Service {
    /**
     * Gets information of the session with the given id.
     *
     * @param sessionId id of the session
     * @param sessionId the ID of the session
     * @return information of the session with the given id.
     *         null if the session is released or ID is not valid.
     */
@@ -218,7 +218,7 @@ public abstract class MediaRoute2ProviderService extends Service {
     * If this session is created without any creation request, use {@link #REQUEST_ID_NONE}
     * as the request ID.
     *
     * @param requestId id of the previous request to create this session provided in
     * @param requestId the ID of the previous request to create this session provided in
     *                  {@link #onCreateSession(long, String, String, Bundle)}. Can be
     *                  {@link #REQUEST_ID_NONE} if this session is created without any request.
     * @param sessionInfo information of the new session.
@@ -237,20 +237,17 @@ public abstract class MediaRoute2ProviderService extends Service {
                return;
            }
            mSessionInfo.put(sessionInfo.getId(), sessionInfo);
        }

            if (mRemoteCallback == null) {
                return;
            }
            try {
            // TODO(b/157873487): Calling binder calls in multiple thread may cause timing issue.
            //       Consider to change implementations to avoid the problems.
            //       For example, post binder calls, always send all sessions at once, etc.
                mRemoteCallback.notifySessionCreated(requestId, sessionInfo);
            } catch (RemoteException ex) {
                Log.w(TAG, "Failed to notify session created.");
            }
        }
    }

    /**
     * Notifies the existing session is updated. For example, when
@@ -267,7 +264,6 @@ public abstract class MediaRoute2ProviderService extends Service {
                Log.w(TAG, "Ignoring unknown session info.");
                return;
            }
        }

            if (mRemoteCallback == null) {
                return;
@@ -278,11 +274,12 @@ public abstract class MediaRoute2ProviderService extends Service {
                Log.w(TAG, "Failed to notify session info changed.");
            }
        }
    }

    /**
     * Notifies that the session is released.
     *
     * @param sessionId id of the released session.
     * @param sessionId the ID of the released session.
     * @see #onReleaseSession(long, String)
     */
    public final void notifySessionReleased(@NonNull String sessionId) {
@@ -292,7 +289,6 @@ public abstract class MediaRoute2ProviderService extends Service {
        RoutingSessionInfo sessionInfo;
        synchronized (mSessionLock) {
            sessionInfo = mSessionInfo.remove(sessionId);
        }

            if (sessionInfo == null) {
                Log.w(TAG, "Ignoring unknown session info.");
@@ -308,6 +304,7 @@ public abstract class MediaRoute2ProviderService extends Service {
                Log.w(TAG, "Failed to notify session info changed.");
            }
        }
    }

    /**
     * Notifies to the client that the request has failed.
@@ -348,9 +345,9 @@ public abstract class MediaRoute2ProviderService extends Service {
     * If you can't create the session or want to reject the request, call
     * {@link #notifyRequestFailed(long, int)} with the given {@code requestId}.
     *
     * @param requestId the id of this request
     * @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 routeId the ID of the route initially being connected
     * @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.
@@ -372,8 +369,8 @@ 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.
     * @param requestId the ID of this request
     * @param sessionId the ID of the session being released.
     * @see #notifySessionReleased(String)
     * @see #getSessionInfo(String)
     */
@@ -384,9 +381,9 @@ public abstract class MediaRoute2ProviderService extends Service {
     * 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
     * @param requestId the ID of this request
     * @param sessionId the ID of the session
     * @param routeId the ID of the route
     */
    public abstract void onSelectRoute(long requestId, @NonNull String sessionId,
            @NonNull String routeId);
@@ -396,9 +393,9 @@ public abstract class MediaRoute2ProviderService extends Service {
     * 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
     * @param requestId the ID of this request
     * @param sessionId the ID of the session
     * @param routeId the ID of the route
     */
    public abstract void onDeselectRoute(long requestId, @NonNull String sessionId,
            @NonNull String routeId);
@@ -408,9 +405,9 @@ public abstract class MediaRoute2ProviderService extends Service {
     * 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
     * @param requestId the ID of this request
     * @param sessionId the ID of the session
     * @param routeId the ID of the route
     */
    public abstract void onTransferToRoute(long requestId, @NonNull String sessionId,
            @NonNull String routeId);
@@ -475,13 +472,39 @@ public abstract class MediaRoute2ProviderService extends Service {
    final class MediaRoute2ProviderServiceStub extends IMediaRoute2ProviderService.Stub {
        MediaRoute2ProviderServiceStub() { }

        boolean checkCallerisSystem() {
        private boolean checkCallerIsSystem() {
            return Binder.getCallingUid() == Process.SYSTEM_UID;
        }

        private boolean checkSessionIdIsValid(String sessionId, String description) {
            if (TextUtils.isEmpty(sessionId)) {
                Log.w(TAG, description + ": Ignoring empty sessionId from system service.");
                return false;
            }
            if (getSessionInfo(sessionId) == null) {
                Log.w(TAG, description + ": Ignoring unknown session from system service. "
                        + "sessionId=" + sessionId);
                return false;
            }
            return true;
        }

        private boolean checkRouteIdIsValid(String routeId, String description) {
            if (TextUtils.isEmpty(routeId)) {
                Log.w(TAG, description + ": Ignoring empty routeId from system service.");
                return false;
            }
            if (mProviderInfo == null || mProviderInfo.getRoute(routeId) == null) {
                Log.w(TAG, description + ": Ignoring unknown route from system service. "
                        + "routeId=" + routeId);
                return false;
            }
            return true;
        }

        @Override
        public void setCallback(IMediaRoute2ProviderServiceCallback callback) {
            if (!checkCallerisSystem()) {
            if (!checkCallerIsSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::setCallback,
@@ -490,7 +513,7 @@ public abstract class MediaRoute2ProviderService extends Service {

        @Override
        public void updateDiscoveryPreference(RouteDiscoveryPreference discoveryPreference) {
            if (!checkCallerisSystem()) {
            if (!checkCallerIsSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(
@@ -500,7 +523,10 @@ public abstract class MediaRoute2ProviderService extends Service {

        @Override
        public void setRouteVolume(long requestId, String routeId, int volume) {
            if (!checkCallerisSystem()) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkRouteIdIsValid(routeId, "setRouteVolume")) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetRouteVolume,
@@ -510,7 +536,10 @@ public abstract class MediaRoute2ProviderService extends Service {
        @Override
        public void requestCreateSession(long requestId, String packageName, String routeId,
                @Nullable Bundle requestCreateSession) {
            if (!checkCallerisSystem()) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkRouteIdIsValid(routeId, "requestCreateSession")) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onCreateSession,
@@ -518,14 +547,13 @@ public abstract class MediaRoute2ProviderService extends Service {
                    requestCreateSession));
        }

        //TODO(b/157873546): Ignore requests with unknown session ID. -> For all similar commands.
        @Override
        public void selectRoute(long requestId, String sessionId, String routeId) {
            if (!checkCallerisSystem()) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (TextUtils.isEmpty(sessionId)) {
                Log.w(TAG, "selectRoute: Ignoring empty sessionId from system service.");
            if (!checkSessionIdIsValid(sessionId, "selectRoute")
                    || !checkRouteIdIsValid(routeId, "selectRoute")) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelectRoute,
@@ -534,11 +562,11 @@ public abstract class MediaRoute2ProviderService extends Service {

        @Override
        public void deselectRoute(long requestId, String sessionId, String routeId) {
            if (!checkCallerisSystem()) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (TextUtils.isEmpty(sessionId)) {
                Log.w(TAG, "deselectRoute: Ignoring empty sessionId from system service.");
            if (!checkSessionIdIsValid(sessionId, "deselectRoute")
                    || !checkRouteIdIsValid(routeId, "deselectRoute")) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onDeselectRoute,
@@ -547,11 +575,11 @@ public abstract class MediaRoute2ProviderService extends Service {

        @Override
        public void transferToRoute(long requestId, String sessionId, String routeId) {
            if (!checkCallerisSystem()) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (TextUtils.isEmpty(sessionId)) {
                Log.w(TAG, "transferToRoute: Ignoring empty sessionId from system service.");
            if (!checkSessionIdIsValid(sessionId, "transferToRoute")
                    || !checkRouteIdIsValid(routeId, "transferToRoute")) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onTransferToRoute,
@@ -560,7 +588,10 @@ public abstract class MediaRoute2ProviderService extends Service {

        @Override
        public void setSessionVolume(long requestId, String sessionId, int volume) {
            if (!checkCallerisSystem()) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (!checkSessionIdIsValid(sessionId, "setSessionVolume")) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetSessionVolume,
@@ -569,11 +600,10 @@ public abstract class MediaRoute2ProviderService extends Service {

        @Override
        public void releaseSession(long requestId, String sessionId) {
            if (!checkCallerisSystem()) {
            if (!checkCallerIsSystem()) {
                return;
            }
            if (TextUtils.isEmpty(sessionId)) {
                Log.w(TAG, "releaseSession: Ignoring empty sessionId from system service.");
            if (!checkSessionIdIsValid(sessionId, "releaseSession")) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onReleaseSession,