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

Commit 7b36ffb0 authored by Kyunglyul Hyun's avatar Kyunglyul Hyun Committed by Android (Google) Code Review
Browse files

Merge "MediaRouter: add session related apis into provider"

parents c7186312 cb8894db
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -24,10 +24,14 @@ import android.media.IMediaRoute2ProviderClient;
 */
oneway interface IMediaRoute2Provider {
    void setClient(IMediaRoute2ProviderClient client);
    void requestCreateSession(String packageName, String routeId, String controlCategory,
            int requestId);
    void requestSelectRoute(String packageName, String id, int seq);
    void unselectRoute(String packageName, String id);
    void requestCreateSession(String packageName, String routeId,
            String controlCategory, int requestId);
    void releaseSession(int sessionId);

    void addRoute(int sessionId, String routeId);
    void removeRoute(int sessionId, String routeId);
    void transferRoute(int sessionId, String routeId);

    void notifyControlRequestSent(String id, in Intent request);
    void requestSetVolume(String id, int volume);
    void requestUpdateVolume(String id, int delta);
+0 −2
Original line number Diff line number Diff line
@@ -26,7 +26,5 @@ import android.os.Bundle;
 */
oneway interface IMediaRoute2ProviderClient {
    void updateProviderInfo(in MediaRoute2ProviderInfo info);
    void notifyRouteSelected(String packageName, String routeId, in @nullable Bundle controlHints,
            int seq);
    void notifySessionCreated(in @nullable RouteSessionInfo sessionInfo, int requestId);
}
+3 −9
Original line number Diff line number Diff line
@@ -55,15 +55,9 @@ interface IMediaRouterService {

    void registerManager(IMediaRouter2Manager manager, String packageName);
    void unregisterManager(IMediaRouter2Manager manager);
    /**
     * Changes the selected route of an application.
     *
     * @param manager the manager that calls the method
     * @param packageName the package name of the client that will change the selected route
     * @param route the route to be selected
     */
    void selectClientRoute2(IMediaRouter2Manager manager, String packageName,
            in @nullable MediaRoute2Info route);

    void requestCreateClientSession(IMediaRouter2Manager manager, String packageName,
        in @nullable MediaRoute2Info route, int requestId);

    void requestSetVolume2Manager(IMediaRouter2Manager manager,
            in MediaRoute2Info route, int volume);
+66 −76
Original line number Diff line number Diff line
@@ -22,10 +22,12 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
@@ -47,7 +49,6 @@ public abstract class MediaRoute2ProviderService extends Service {
    private final Handler mHandler;
    private final Object mSessionLock = new Object();
    private ProviderStub mStub;
    // TODO: Rename this to mService (and accordingly IMediaRoute2ProviderClient to something else)
    private IMediaRoute2ProviderClient mClient;
    private MediaRoute2ProviderInfo mProviderInfo;

@@ -70,28 +71,6 @@ public abstract class MediaRoute2ProviderService extends Service {
        return null;
    }

    /**
     * Called when selectRoute is called on a route of the provider.
     * Once the route is ready to be used , call {@link #notifyRouteSelected(SelectToken, Bundle)}
     * to notify that.
     *
     * @param packageName the package name of the application that selected the route
     * @param routeId the id of the route being selected
     * @param token token that contains select info
     *
     * @see #notifyRouteSelected
     */
    public abstract void onSelectRoute(@NonNull String packageName, @NonNull String routeId,
            @NonNull SelectToken token);

    /**
     * Called when unselectRoute is called on a route of the provider.
     *
     * @param packageName the package name of the application that has selected the route.
     * @param routeId the id of the route being unselected
     */
    public abstract void onUnselectRoute(@NonNull String packageName, @NonNull String routeId);

    /**
     * Called when sendControlRequest is called on a route of the provider
     *
@@ -155,6 +134,8 @@ public abstract class MediaRoute2ProviderService extends Service {
        Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
        int sessionId = sessionInfo.getSessionId();

        //TODO: notify updated session info

        synchronized (mSessionLock) {
            if (mSessionInfo.containsKey(sessionId)) {
                mSessionInfo.put(sessionId, sessionInfo);
@@ -162,6 +143,9 @@ public abstract class MediaRoute2ProviderService extends Service {
                Log.w(TAG, "Ignoring unknown session info.");
            }
        }
        if (sessionInfo.getSelectedRoutes().isEmpty()) {
            releaseSession(sessionId);
        }
    }

    /**
@@ -169,15 +153,20 @@ public abstract class MediaRoute2ProviderService extends Service {
     * controlled, pass a {@link Bundle} that contains how to control it.
     *
     * @param sessionInfo information of the new session.
     *                    Pass {@code null} to reject the request or inform clients that
     *                    session creation has failed.
     *                    The {@link RouteSessionInfo#getSessionId() id} of the session must be
     *                    unique. Pass {@code null} to reject the request or inform clients that
     *                    session creation is failed.
     * @param requestId id of the previous request to create this session
     */
    //TODO: fail reason?
    public final void notifySessionCreated(@Nullable RouteSessionInfo sessionInfo, int requestId) {
        //TODO: validate sessionInfo.getSessionId() (it must be in "waiting list")
        if (sessionInfo != null) {
            int sessionId = sessionInfo.getSessionId();
            synchronized (mSessionLock) {
                if (mSessionInfo.containsKey(sessionId)) {
                    Log.w(TAG, "Ignoring duplicate session id.");
                    return;
                }
                mSessionInfo.put(sessionInfo.getSessionId(), sessionInfo);
            }
        }
@@ -200,6 +189,7 @@ public abstract class MediaRoute2ProviderService extends Service {
     * @see #onDestroySession(int, RouteSessionInfo)
     */
    public final void releaseSession(int sessionId) {
        //TODO: notify media router service of release.
        RouteSessionInfo sessionInfo;
        synchronized (mSessionLock) {
            sessionInfo = mSessionInfo.put(sessionId, null);
@@ -283,29 +273,6 @@ public abstract class MediaRoute2ProviderService extends Service {
        publishState();
    }

    /**
     * Notifies the client of that the selected route is ready for use. If the selected route can be
     * controlled, pass a {@link Bundle} that contains how to control it.
     *
     * @param token token passed in {@link #onSelectRoute}
     * @param controlHints a {@link Bundle} that contains how to control the given route.
     * Pass {@code null} if the route is not available.
     */
    public final void notifyRouteSelected(@NonNull SelectToken token,
            @Nullable Bundle controlHints) {
        Objects.requireNonNull(token, "token must not be null");

        if (mClient == null) {
            return;
        }
        try {
            mClient.notifyRouteSelected(token.mPackageName, token.mRouteId,
                    controlHints, token.mSeq);
        } catch (RemoteException ex) {
            Log.w(TAG, "Failed to notify route selected");
        }
    }

    void setClient(IMediaRoute2ProviderClient client) {
        mClient = client;
        publishState();
@@ -323,68 +290,91 @@ public abstract class MediaRoute2ProviderService extends Service {
        }
    }

    /**
     * Route selection information.
     *
     * @see #notifyRouteSelected
     */
    public final class SelectToken {
        final String mPackageName;
        final String mRouteId;
        final int mSeq;

        SelectToken(String packageName, String routeId, int seq) {
            mPackageName = packageName;
            mRouteId = routeId;
            mSeq = seq;
        }
    }

    final class ProviderStub extends IMediaRoute2Provider.Stub {
        ProviderStub() { }

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

        @Override
        public void setClient(IMediaRoute2ProviderClient client) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::setClient,
                    MediaRoute2ProviderService.this, client));
        }

        @Override
        public void requestCreateSession(String packageName, String routeId, String controlCategory,
                int requestId) {
        public void requestCreateSession(String packageName, String routeId,
                String controlCategory, int requestId) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onCreateSession,
                    MediaRoute2ProviderService.this, packageName, routeId, controlCategory,
                    requestId));
        }
        @Override
        public void releaseSession(int sessionId) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::releaseSession,
                    MediaRoute2ProviderService.this, sessionId));
        }

        @Override
        public void requestSelectRoute(String packageName, String routeId, int seq) {
            //TODO: call onCreateSession instead
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelectRoute,
                    MediaRoute2ProviderService.this, packageName, routeId,
                    new SelectToken(packageName, routeId, seq)));
        public void addRoute(int sessionId, String routeId) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onAddRoute,
                    MediaRoute2ProviderService.this, sessionId, routeId));
        }

        @Override
        public void unselectRoute(String packageName, String routeId) {
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUnselectRoute,
                    MediaRoute2ProviderService.this, packageName, routeId));
        public void removeRoute(int sessionId, String routeId) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onRemoveRoute,
                    MediaRoute2ProviderService.this, sessionId, routeId));
        }

        @Override
        public void transferRoute(int sessionId, String routeId) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onTransferRoute,
                    MediaRoute2ProviderService.this, sessionId, routeId));
        }

        @Override
        public void notifyControlRequestSent(String routeId, Intent request) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onControlRequest,
                    MediaRoute2ProviderService.this, routeId, request));
        }

        @Override
        public void requestSetVolume(String routeId, int volume) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetVolume,
                    MediaRoute2ProviderService.this, routeId, volume));
        }

        @Override
        public void requestUpdateVolume(String routeId, int delta) {
            if (!checkCallerisSystem()) {
                return;
            }
            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUpdateVolume,
                    MediaRoute2ProviderService.this, routeId, delta));
        }
+9 −21
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.os.Handler;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
@@ -40,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @hide
@@ -66,6 +68,8 @@ public class MediaRouter2Manager {
    @NonNull
    final ConcurrentMap<String, List<String>> mControlCategoryMap = new ConcurrentHashMap<>();

    private AtomicInteger mNextRequestId = new AtomicInteger(1);

    /**
     * Gets an instance of media router manager that controls media route of other applications.
     *
@@ -204,7 +208,7 @@ public class MediaRouter2Manager {
     * Selects media route for the specified package name.
     *
     * @param packageName the package name of the application that should change it's media route
     * @param route the route to be selected
     * @param route the route to be selected.
     */
    public void selectRoute(@NonNull String packageName, @NonNull MediaRoute2Info route) {
        Objects.requireNonNull(packageName, "packageName must not be null");
@@ -216,26 +220,10 @@ public class MediaRouter2Manager {
        }
        if (client != null) {
            try {
                mMediaRouterService.selectClientRoute2(client, packageName, route);
            } catch (RemoteException ex) {
                Log.e(TAG, "Unable to select media route", ex);
            }
        }
    }

    /**
     * Unselects media route for the specified package name.
     *
     * @param packageName the package name of the application that should stop routing
     */
    public void unselectRoute(@NonNull String packageName) {
        Client client;
        synchronized (sLock) {
            client = mClient;
        }
        if (client != null) {
            try {
                mMediaRouterService.selectClientRoute2(client, packageName, null);
                //TODO: make request id globally unique
                int requestId = Process.myPid() * 10000 + mNextRequestId.getAndIncrement();
                mMediaRouterService.requestCreateClientSession(
                        client, packageName, route, requestId);
            } catch (RemoteException ex) {
                Log.e(TAG, "Unable to select media route", ex);
            }
Loading