Merge "MediaRouter: add session related apis into provider"
This commit is contained in:
committed by
Android (Google) Code Review
commit
7b36ffb06c
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 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 releaseSession(int sessionId) {
|
||||
if (!checkCallerisSystem()) {
|
||||
return;
|
||||
}
|
||||
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::releaseSession,
|
||||
MediaRoute2ProviderService.this, sessionId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unselectRoute(String packageName, String routeId) {
|
||||
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUnselectRoute,
|
||||
MediaRoute2ProviderService.this, packageName, routeId));
|
||||
public void addRoute(int sessionId, String routeId) {
|
||||
if (!checkCallerisSystem()) {
|
||||
return;
|
||||
}
|
||||
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onAddRoute,
|
||||
MediaRoute2ProviderService.this, sessionId, routeId));
|
||||
}
|
||||
|
||||
@Override
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -49,10 +49,13 @@ public class RouteSessionInfo implements Parcelable {
|
||||
final int mSessionId;
|
||||
final String mPackageName;
|
||||
final String mControlCategory;
|
||||
@Nullable
|
||||
final String mProviderId;
|
||||
final List<String> mSelectedRoutes;
|
||||
final List<String> mDeselectableRoutes;
|
||||
final List<String> mGroupableRoutes;
|
||||
final List<String> mTransferrableRoutes;
|
||||
@Nullable
|
||||
final Bundle mControlHints;
|
||||
|
||||
RouteSessionInfo(@NonNull Builder builder) {
|
||||
@@ -61,6 +64,7 @@ public class RouteSessionInfo implements Parcelable {
|
||||
mSessionId = builder.mSessionId;
|
||||
mPackageName = builder.mPackageName;
|
||||
mControlCategory = builder.mControlCategory;
|
||||
mProviderId = builder.mProviderId;
|
||||
|
||||
mSelectedRoutes = Collections.unmodifiableList(builder.mSelectedRoutes);
|
||||
mDeselectableRoutes = Collections.unmodifiableList(builder.mDeselectableRoutes);
|
||||
@@ -76,6 +80,7 @@ public class RouteSessionInfo implements Parcelable {
|
||||
mSessionId = src.readInt();
|
||||
mPackageName = ensureString(src.readString());
|
||||
mControlCategory = ensureString(src.readString());
|
||||
mProviderId = src.readString();
|
||||
|
||||
mSelectedRoutes = ensureList(src.createStringArrayList());
|
||||
mDeselectableRoutes = ensureList(src.createStringArrayList());
|
||||
@@ -116,6 +121,14 @@ public class RouteSessionInfo implements Parcelable {
|
||||
return mSessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the client package name of the session
|
||||
*/
|
||||
@NonNull
|
||||
public String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the control category of the session.
|
||||
* Routes that don't support the category can't be added to the session.
|
||||
@@ -125,6 +138,15 @@ public class RouteSessionInfo implements Parcelable {
|
||||
return mControlCategory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the provider id of the session.
|
||||
* @hide
|
||||
*/
|
||||
@Nullable
|
||||
public String getProviderId() {
|
||||
return mProviderId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of ids of selected routes for the session. It shouldn't be empty.
|
||||
*/
|
||||
@@ -175,6 +197,7 @@ public class RouteSessionInfo implements Parcelable {
|
||||
dest.writeInt(mSessionId);
|
||||
dest.writeString(mPackageName);
|
||||
dest.writeString(mControlCategory);
|
||||
dest.writeString(mProviderId);
|
||||
dest.writeStringList(mSelectedRoutes);
|
||||
dest.writeStringList(mDeselectableRoutes);
|
||||
dest.writeStringList(mGroupableRoutes);
|
||||
@@ -187,13 +210,20 @@ public class RouteSessionInfo implements Parcelable {
|
||||
StringBuilder result = new StringBuilder()
|
||||
.append("RouteSessionInfo{ ")
|
||||
.append("sessionId=").append(mSessionId)
|
||||
.append(", selectedRoutes={");
|
||||
for (int i = 0; i < mSelectedRoutes.size(); i++) {
|
||||
if (i > 0) result.append(", ");
|
||||
result.append(mSelectedRoutes.get(i));
|
||||
}
|
||||
result.append("}");
|
||||
result.append(" }");
|
||||
.append(", controlCategory=").append(mControlCategory)
|
||||
.append(", selectedRoutes={")
|
||||
.append(String.join(",", mSelectedRoutes))
|
||||
.append("}")
|
||||
.append(", deselectableRoutes={")
|
||||
.append(String.join(",", mDeselectableRoutes))
|
||||
.append("}")
|
||||
.append(", groupableRoutes={")
|
||||
.append(String.join(",", mGroupableRoutes))
|
||||
.append("}")
|
||||
.append(", transferrableRoutes={")
|
||||
.append(String.join(",", mTransferrableRoutes))
|
||||
.append("}")
|
||||
.append(" }");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@@ -204,6 +234,7 @@ public class RouteSessionInfo implements Parcelable {
|
||||
final String mPackageName;
|
||||
final int mSessionId;
|
||||
final String mControlCategory;
|
||||
String mProviderId;
|
||||
final List<String> mSelectedRoutes;
|
||||
final List<String> mDeselectableRoutes;
|
||||
final List<String> mGroupableRoutes;
|
||||
@@ -227,6 +258,7 @@ public class RouteSessionInfo implements Parcelable {
|
||||
mSessionId = sessionInfo.mSessionId;
|
||||
mPackageName = sessionInfo.mPackageName;
|
||||
mControlCategory = sessionInfo.mControlCategory;
|
||||
mProviderId = sessionInfo.mProviderId;
|
||||
|
||||
mSelectedRoutes = new ArrayList<>(sessionInfo.mSelectedRoutes);
|
||||
mDeselectableRoutes = new ArrayList<>(sessionInfo.mDeselectableRoutes);
|
||||
@@ -236,6 +268,15 @@ public class RouteSessionInfo implements Parcelable {
|
||||
mControlHints = sessionInfo.mControlHints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the provider id of the session.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setProviderId(String providerId) {
|
||||
mProviderId = providerId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the selected routes.
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.media.MediaRoute2Info;
|
||||
import android.media.MediaRoute2ProviderInfo;
|
||||
import android.media.MediaRoute2ProviderService;
|
||||
import android.media.RouteSessionInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.text.TextUtils;
|
||||
|
||||
@@ -62,6 +61,7 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
|
||||
public static final int SESSION_ID_1 = 1000;
|
||||
|
||||
Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
|
||||
Map<String, Integer> mRouteSessionMap = new HashMap<>();
|
||||
|
||||
private void initializeRoutes() {
|
||||
MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1)
|
||||
@@ -112,31 +112,6 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
|
||||
return super.onBind(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectRoute(String packageName, String routeId, SelectToken token) {
|
||||
MediaRoute2Info route = mRoutes.get(routeId);
|
||||
if (route == null) {
|
||||
return;
|
||||
}
|
||||
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
|
||||
.setClientPackageName(packageName)
|
||||
.build());
|
||||
publishRoutes();
|
||||
notifyRouteSelected(token, Bundle.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnselectRoute(String packageName, String routeId) {
|
||||
MediaRoute2Info route = mRoutes.get(routeId);
|
||||
if (route == null) {
|
||||
return;
|
||||
}
|
||||
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
|
||||
.setClientPackageName(null)
|
||||
.build());
|
||||
publishRoutes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControlRequest(String routeId, Intent request) {
|
||||
String action = request.getAction();
|
||||
@@ -180,26 +155,56 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
|
||||
@Override
|
||||
public void onCreateSession(String packageName, String routeId, String controlCategory,
|
||||
int requestId) {
|
||||
if (TextUtils.equals(ROUTE_ID3_SESSION_CREATION_FAILED, routeId)) {
|
||||
MediaRoute2Info route = mRoutes.get(routeId);
|
||||
if (route == null || TextUtils.equals(ROUTE_ID3_SESSION_CREATION_FAILED, routeId)) {
|
||||
// Tell the router that session cannot be created by passing null as sessionInfo.
|
||||
notifySessionCreated(/* sessionInfo= */ null, requestId);
|
||||
return;
|
||||
}
|
||||
maybeRemoveRoute(routeId);
|
||||
|
||||
int sessionId = SESSION_ID_1;
|
||||
|
||||
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
|
||||
.setClientPackageName(packageName)
|
||||
.build());
|
||||
mRouteSessionMap.put(routeId, sessionId);
|
||||
|
||||
RouteSessionInfo sessionInfo = new RouteSessionInfo.Builder(
|
||||
SESSION_ID_1, packageName, controlCategory)
|
||||
sessionId, packageName, controlCategory)
|
||||
.addSelectedRoute(routeId)
|
||||
.build();
|
||||
notifySessionCreated(sessionInfo, requestId);
|
||||
notifySessionCreated(sessionInfo, requestId);
|
||||
publishRoutes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroySession(int sessionId, RouteSessionInfo lastSessionInfo) {}
|
||||
public void onDestroySession(int sessionId, RouteSessionInfo lastSessionInfo) {
|
||||
for (String routeId : lastSessionInfo.getSelectedRoutes()) {
|
||||
mRouteSessionMap.remove(routeId);
|
||||
MediaRoute2Info route = mRoutes.get(routeId);
|
||||
if (route != null) {
|
||||
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
|
||||
.setClientPackageName(null)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAddRoute(int sessionId, String routeId) {
|
||||
RouteSessionInfo sessionInfo = getSessionInfo(sessionId);
|
||||
//TODO: we may want to remove route if it belongs to another session
|
||||
MediaRoute2Info route = mRoutes.get(routeId);
|
||||
if (route == null || sessionInfo == null) {
|
||||
return;
|
||||
}
|
||||
maybeRemoveRoute(routeId);
|
||||
|
||||
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
|
||||
.setClientPackageName(sessionInfo.getPackageName())
|
||||
.build());
|
||||
mRouteSessionMap.put(routeId, sessionId);
|
||||
|
||||
RouteSessionInfo newSessionInfo = new RouteSessionInfo.Builder(sessionInfo)
|
||||
.addSelectedRoute(routeId)
|
||||
.build();
|
||||
@@ -210,6 +215,16 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
|
||||
@Override
|
||||
public void onRemoveRoute(int sessionId, String routeId) {
|
||||
RouteSessionInfo sessionInfo = getSessionInfo(sessionId);
|
||||
MediaRoute2Info route = mRoutes.get(routeId);
|
||||
|
||||
mRouteSessionMap.remove(routeId);
|
||||
if (sessionInfo == null || route == null) {
|
||||
return;
|
||||
}
|
||||
mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
|
||||
.setClientPackageName(null)
|
||||
.build());
|
||||
|
||||
RouteSessionInfo newSessionInfo = new RouteSessionInfo.Builder(sessionInfo)
|
||||
.removeSelectedRoute(routeId)
|
||||
.build();
|
||||
@@ -228,6 +243,15 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
|
||||
publishRoutes();
|
||||
}
|
||||
|
||||
void maybeRemoveRoute(String routeId) {
|
||||
if (!mRouteSessionMap.containsKey(routeId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int sessionId = mRouteSessionMap.get(routeId);
|
||||
onRemoveRoute(sessionId, routeId);
|
||||
}
|
||||
|
||||
void publishRoutes() {
|
||||
MediaRoute2ProviderInfo info = new MediaRoute2ProviderInfo.Builder()
|
||||
.addRoutes(mRoutes.values())
|
||||
|
||||
@@ -226,7 +226,8 @@ public class MediaRouterManagerTest {
|
||||
mManager.selectRoute(mPackageName, routeToSelect);
|
||||
assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
} finally {
|
||||
mManager.unselectRoute(mPackageName);
|
||||
//TODO: release the session
|
||||
//mManager.selectRoute(mPackageName, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +235,7 @@ public class MediaRouterManagerTest {
|
||||
* Tests if MR2Manager.Callback.onRouteSelected is called
|
||||
* when a route is selected by MR2Manager.
|
||||
*/
|
||||
@Test
|
||||
//TODO: test session created callback instead of onRouteSelected
|
||||
public void testManagerOnRouteSelected() throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
|
||||
@@ -257,14 +258,14 @@ public class MediaRouterManagerTest {
|
||||
mManager.selectRoute(mPackageName, routeToSelect);
|
||||
assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
|
||||
} finally {
|
||||
mManager.unselectRoute(mPackageName);
|
||||
//TODO: release the session
|
||||
//mManager.selectRoute(mPackageName, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
//TODO: enable this when "releasing session" is implemented
|
||||
public void testGetActiveRoutes() throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
CountDownLatch latch2 = new CountDownLatch(1);
|
||||
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
|
||||
addRouterCallback(new RouteCallback());
|
||||
@@ -278,6 +279,7 @@ public class MediaRouterManagerTest {
|
||||
}
|
||||
});
|
||||
|
||||
//TODO: it fails due to not releasing session
|
||||
assertEquals(0, mManager.getActiveRoutes().size());
|
||||
|
||||
mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
|
||||
@@ -285,17 +287,20 @@ public class MediaRouterManagerTest {
|
||||
|
||||
assertEquals(1, mManager.getActiveRoutes().size());
|
||||
|
||||
//TODO: release the session
|
||||
/*
|
||||
awaitOnRouteChangedManager(
|
||||
() -> mManager.unselectRoute(mPackageName),
|
||||
() -> mManager.selectRoute(mPackageName, null),
|
||||
ROUTE_ID1,
|
||||
route -> TextUtils.equals(route.getClientPackageName(), null));
|
||||
assertEquals(0, mManager.getActiveRoutes().size());
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests selecting and unselecting routes of a single provider.
|
||||
*/
|
||||
@Test
|
||||
//TODO: @Test when session is released
|
||||
public void testSingleProviderSelect() throws Exception {
|
||||
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(CATEGORIES_ALL);
|
||||
addRouterCallback(new RouteCallback());
|
||||
@@ -310,10 +315,14 @@ public class MediaRouterManagerTest {
|
||||
ROUTE_ID2,
|
||||
route -> TextUtils.equals(route.getClientPackageName(), mPackageName));
|
||||
|
||||
//TODO: release the session
|
||||
/*
|
||||
awaitOnRouteChangedManager(
|
||||
() -> mManager.unselectRoute(mPackageName),
|
||||
() -> mManager.selectRoute(mPackageName, null),
|
||||
ROUTE_ID2,
|
||||
route -> TextUtils.equals(route.getClientPackageName(), null));
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -23,7 +23,6 @@ import android.content.Intent;
|
||||
import android.media.MediaRoute2Info;
|
||||
import android.media.MediaRoute2ProviderInfo;
|
||||
import android.media.RouteSessionInfo;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -45,8 +44,12 @@ abstract class MediaRoute2Provider {
|
||||
|
||||
public abstract void requestCreateSession(String packageName, String routeId,
|
||||
String controlCategory, int requestId);
|
||||
public abstract void requestSelectRoute(String packageName, String routeId, int seq);
|
||||
public abstract void unselectRoute(String packageName, String routeId);
|
||||
public abstract void releaseSession(int sessionId);
|
||||
|
||||
public abstract void addRoute(int sessionId, MediaRoute2Info route);
|
||||
public abstract void removeRoute(int sessionId, MediaRoute2Info route);
|
||||
public abstract void transferRoute(int sessionId, MediaRoute2Info route);
|
||||
|
||||
public abstract void sendControlRequest(MediaRoute2Info route, Intent request);
|
||||
public abstract void requestSetVolume(MediaRoute2Info route, int volume);
|
||||
public abstract void requestUpdateVolume(MediaRoute2Info route, int delta);
|
||||
@@ -82,9 +85,6 @@ abstract class MediaRoute2Provider {
|
||||
|
||||
public interface Callback {
|
||||
void onProviderStateChanged(@Nullable MediaRoute2Provider provider);
|
||||
void onRouteSelected(@NonNull MediaRoute2ProviderProxy provider,
|
||||
@NonNull String clientPackageName, @NonNull MediaRoute2Info route,
|
||||
@Nullable Bundle controlHints, int seq);
|
||||
void onSessionCreated(@NonNull MediaRoute2Provider provider,
|
||||
@Nullable RouteSessionInfo sessionInfo, int requestId);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.media.MediaRoute2Info;
|
||||
import android.media.MediaRoute2ProviderInfo;
|
||||
import android.media.MediaRoute2ProviderService;
|
||||
import android.media.RouteSessionInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
@@ -86,18 +85,31 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestSelectRoute(String packageName, String routeId, int seq) {
|
||||
public void releaseSession(int sessionId) {
|
||||
if (mConnectionReady) {
|
||||
mActiveConnection.requestSelectRoute(packageName, routeId, seq);
|
||||
mActiveConnection.releaseSession(sessionId);
|
||||
updateBinding();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unselectRoute(String packageName, String routeId) {
|
||||
public void addRoute(int sessionId, MediaRoute2Info route) {
|
||||
if (mConnectionReady) {
|
||||
mActiveConnection.unselectRoute(packageName, routeId);
|
||||
updateBinding();
|
||||
mActiveConnection.addRoute(sessionId, route.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRoute(int sessionId, MediaRoute2Info route) {
|
||||
if (mConnectionReady) {
|
||||
mActiveConnection.removeRoute(sessionId, route.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferRoute(int sessionId, MediaRoute2Info route) {
|
||||
if (mConnectionReady) {
|
||||
mActiveConnection.transferRoute(sessionId, route.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,20 +278,6 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
setAndNotifyProviderInfo(info);
|
||||
}
|
||||
|
||||
private void onRouteSelected(Connection connection,
|
||||
String packageName, String routeId, Bundle controlHints, int seq) {
|
||||
if (mActiveConnection != connection) {
|
||||
return;
|
||||
}
|
||||
MediaRoute2ProviderInfo providerInfo = getProviderInfo();
|
||||
MediaRoute2Info route = (providerInfo == null) ? null : providerInfo.getRoute(routeId);
|
||||
if (route == null) {
|
||||
Slog.w(TAG, this + ": Unknown route " + routeId + " is selected from remove provider");
|
||||
return;
|
||||
}
|
||||
mCallback.onRouteSelected(this, packageName, route, controlHints, seq);
|
||||
}
|
||||
|
||||
private void onSessionCreated(Connection connection, @Nullable RouteSessionInfo sessionInfo,
|
||||
int requestId) {
|
||||
if (mActiveConnection != connection) {
|
||||
@@ -331,25 +329,42 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
public void requestCreateSession(String packageName, String routeId, String controlCategory,
|
||||
int requestId) {
|
||||
try {
|
||||
mProvider.requestCreateSession(packageName, routeId, controlCategory, requestId);
|
||||
mProvider.requestCreateSession(packageName, routeId,
|
||||
controlCategory, requestId);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.e(TAG, "Failed to deliver request to create a session.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void requestSelectRoute(String packageName, String routeId, int seq) {
|
||||
public void releaseSession(int sessionId) {
|
||||
try {
|
||||
mProvider.requestSelectRoute(packageName, routeId, seq);
|
||||
mProvider.releaseSession(sessionId);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.e(TAG, "Failed to deliver request to set discovery mode.", ex);
|
||||
Slog.e(TAG, "Failed to deliver request to release a session.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void unselectRoute(String packageName, String routeId) {
|
||||
public void addRoute(int sessionId, String routeId) {
|
||||
try {
|
||||
mProvider.unselectRoute(packageName, routeId);
|
||||
mProvider.addRoute(sessionId, routeId);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.e(TAG, "Failed to deliver request to set discovery mode.", ex);
|
||||
Slog.e(TAG, "Failed to deliver request to add a route to a session.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeRoute(int sessionId, String routeId) {
|
||||
try {
|
||||
mProvider.removeRoute(sessionId, routeId);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.e(TAG, "Failed to deliver request to remove a route from a session.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void transferRoute(int sessionId, String routeId) {
|
||||
try {
|
||||
mProvider.transferRoute(sessionId, routeId);
|
||||
} catch (RemoteException ex) {
|
||||
Slog.e(TAG, "Failed to deliver request to transfer a session to a route.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,11 +401,6 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
mHandler.post(() -> onProviderInfoUpdated(Connection.this, info));
|
||||
}
|
||||
|
||||
void postRouteSelected(String packageName, String routeId, Bundle controlHints, int seq) {
|
||||
mHandler.post(() -> onRouteSelected(Connection.this,
|
||||
packageName, routeId, controlHints, seq));
|
||||
}
|
||||
|
||||
void postSessionCreated(@Nullable RouteSessionInfo sessionInfo, int requestId) {
|
||||
mHandler.post(() -> onSessionCreated(Connection.this, sessionInfo,
|
||||
requestId));
|
||||
@@ -416,15 +426,6 @@ final class MediaRoute2ProviderProxy extends MediaRoute2Provider implements Serv
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyRouteSelected(String packageName, String routeId,
|
||||
Bundle controlHints, int seq) {
|
||||
Connection connection = mConnectionRef.get();
|
||||
if (connection != null) {
|
||||
connection.postRouteSelected(packageName, routeId, controlHints, seq);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySessionCreated(@Nullable RouteSessionInfo sessionInfo, int requestId) {
|
||||
Connection connection = mConnectionRef.get();
|
||||
|
||||
@@ -28,14 +28,12 @@ import android.media.IMediaRouter2Client;
|
||||
import android.media.IMediaRouter2Manager;
|
||||
import android.media.MediaRoute2Info;
|
||||
import android.media.MediaRoute2ProviderInfo;
|
||||
import android.media.MediaRouter2;
|
||||
import android.media.RouteSessionInfo;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
@@ -77,8 +75,6 @@ class MediaRouter2ServiceImpl {
|
||||
private final ArrayMap<IBinder, ManagerRecord> mAllManagerRecords = new ArrayMap<>();
|
||||
@GuardedBy("mLock")
|
||||
private int mCurrentUserId = -1;
|
||||
@GuardedBy("mLock")
|
||||
private int mSelectRouteRequestSequenceNumber = 1;
|
||||
|
||||
MediaRouter2ServiceImpl(Context context) {
|
||||
mContext = context;
|
||||
@@ -246,12 +242,12 @@ class MediaRouter2ServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
public void selectClientRoute2(@NonNull IMediaRouter2Manager manager,
|
||||
String packageName, @Nullable MediaRoute2Info route) {
|
||||
public void requestCreateClientSession(IMediaRouter2Manager manager, String packageName,
|
||||
MediaRoute2Info route, int requestId) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
selectClientRoute2Locked(manager, packageName, route);
|
||||
requestClientCreateSessionLocked(manager, packageName, route, requestId);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
@@ -374,42 +370,6 @@ class MediaRouter2ServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private void requestSelectRoute2Locked(Client2Record clientRecord, boolean selectedByManager,
|
||||
MediaRoute2Info route) {
|
||||
if (clientRecord != null) {
|
||||
MediaRoute2Info oldRoute = clientRecord.mSelectedRoute;
|
||||
clientRecord.mSelectingRoute = route;
|
||||
clientRecord.mIsManagerSelecting = selectedByManager;
|
||||
|
||||
UserHandler handler = clientRecord.mUserRecord.mHandler;
|
||||
//TODO: Handle transfer instead of unselect and select
|
||||
if (oldRoute != null) {
|
||||
handler.sendMessage(obtainMessage(
|
||||
UserHandler::unselectRoute, handler, clientRecord.mPackageName, oldRoute));
|
||||
}
|
||||
if (route != null) {
|
||||
final int seq = mSelectRouteRequestSequenceNumber;
|
||||
mSelectRouteRequestSequenceNumber++;
|
||||
|
||||
handler.sendMessage(obtainMessage(
|
||||
UserHandler::requestSelectRoute, handler, clientRecord.mPackageName,
|
||||
route, seq));
|
||||
// Remove all previous timeout messages
|
||||
for (int previousSeq : clientRecord.mSelectRouteSequenceNumbers) {
|
||||
clientRecord.mUserRecord.mHandler.removeMessages(previousSeq);
|
||||
}
|
||||
clientRecord.mSelectRouteSequenceNumbers.clear();
|
||||
|
||||
// When the request is not handled in timeout, set the client's route to default.
|
||||
Message timeoutMsg = obtainMessage(UserHandler::handleRouteSelectionTimeout,
|
||||
handler, clientRecord.mPackageName, route);
|
||||
timeoutMsg.what = seq; // Make the message cancelable.
|
||||
handler.sendMessageDelayed(timeoutMsg, ROUTE_SELECTION_REQUEST_TIMEOUT_MS);
|
||||
clientRecord.mSelectRouteSequenceNumbers.add(seq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setControlCategoriesLocked(Client2Record clientRecord, List<String> categories) {
|
||||
if (clientRecord != null) {
|
||||
if (clientRecord.mControlCategories.equals(categories)) {
|
||||
@@ -512,17 +472,19 @@ class MediaRouter2ServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private void selectClientRoute2Locked(IMediaRouter2Manager manager,
|
||||
String packageName, MediaRoute2Info route) {
|
||||
private void requestClientCreateSessionLocked(IMediaRouter2Manager manager,
|
||||
String packageName, MediaRoute2Info route, int requestId) {
|
||||
ManagerRecord managerRecord = mAllManagerRecords.get(manager.asBinder());
|
||||
if (managerRecord != null) {
|
||||
Client2Record clientRecord =
|
||||
managerRecord.mUserRecord.findClientRecordLocked(packageName);
|
||||
if (clientRecord == null) {
|
||||
Slog.w(TAG, "Ignoring route selection for unknown client.");
|
||||
Slog.w(TAG, "Ignoring session creation for unknown client.");
|
||||
}
|
||||
if (clientRecord != null && managerRecord.mTrusted) {
|
||||
requestSelectRoute2Locked(clientRecord, true, route);
|
||||
//TODO: select category properly
|
||||
requestCreateSessionLocked(clientRecord.mClient, route,
|
||||
route.getSupportedCategories().get(0), requestId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -551,7 +513,6 @@ class MediaRouter2ServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initializeUserLocked(UserRecord userRecord) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, userRecord + ": Initialized");
|
||||
@@ -737,14 +698,6 @@ class MediaRouter2ServiceImpl {
|
||||
sendMessage(PooledLambda.obtainMessage(UserHandler::updateProvider, this, provider));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRouteSelected(@NonNull MediaRoute2ProviderProxy provider,
|
||||
String clientPackageName, MediaRoute2Info route, Bundle controlHints, int seq) {
|
||||
sendMessage(PooledLambda.obtainMessage(
|
||||
UserHandler::updateSelectedRoute, this, provider, clientPackageName, route,
|
||||
controlHints, seq));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSessionCreated(@NonNull MediaRoute2Provider provider,
|
||||
@Nullable RouteSessionInfo sessionInfo, int requestId) {
|
||||
@@ -865,6 +818,7 @@ class MediaRouter2ServiceImpl {
|
||||
@NonNull MediaRoute2Provider provider, @Nullable RouteSessionInfo sessionInfo,
|
||||
int requestId) {
|
||||
SessionCreationRequest matchingRequest = null;
|
||||
|
||||
for (SessionCreationRequest request : mSessionCreationRequests) {
|
||||
if (request.mRequestId == requestId
|
||||
&& TextUtils.equals(
|
||||
@@ -880,26 +834,34 @@ class MediaRouter2ServiceImpl {
|
||||
return;
|
||||
}
|
||||
|
||||
mSessionCreationRequests.remove(matchingRequest);
|
||||
|
||||
if (sessionInfo == null) {
|
||||
// Failed
|
||||
notifySessionCreationFailed(matchingRequest.mClientRecord, requestId);
|
||||
return;
|
||||
}
|
||||
|
||||
RouteSessionInfo sessionInfoWithProviderId = new RouteSessionInfo.Builder(sessionInfo)
|
||||
.setProviderId(provider.getUniqueId())
|
||||
.build();
|
||||
|
||||
String originalRouteId = matchingRequest.mRoute.getId();
|
||||
String originalCategory = matchingRequest.mControlCategory;
|
||||
if (!sessionInfo.getSelectedRoutes().contains(originalRouteId)
|
||||
|| !TextUtils.equals(originalCategory, sessionInfo.getControlCategory())) {
|
||||
if (!sessionInfoWithProviderId.getSelectedRoutes().contains(originalRouteId)
|
||||
|| !TextUtils.equals(originalCategory,
|
||||
sessionInfoWithProviderId.getControlCategory())) {
|
||||
Slog.w(TAG, "Created session doesn't match the original request."
|
||||
+ " originalRouteId=" + originalRouteId
|
||||
+ ", originalCategory=" + originalCategory
|
||||
+ ", requestId=" + requestId + ", sessionInfo=" + sessionInfo);
|
||||
+ ", originalCategory=" + originalCategory + ", requestId=" + requestId
|
||||
+ ", sessionInfo=" + sessionInfoWithProviderId);
|
||||
notifySessionCreationFailed(matchingRequest.mClientRecord, requestId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Succeeded
|
||||
notifySessionCreated(matchingRequest.mClientRecord, sessionInfo, requestId);
|
||||
notifySessionCreated(matchingRequest.mClientRecord,
|
||||
sessionInfoWithProviderId, requestId);
|
||||
// TODO: Tell managers for the session creation
|
||||
}
|
||||
|
||||
@@ -922,109 +884,6 @@ class MediaRouter2ServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSelectedRoute(MediaRoute2ProviderProxy provider,
|
||||
String clientPackageName, MediaRoute2Info selectedRoute, Bundle controlHints,
|
||||
int seq) {
|
||||
if (selectedRoute == null
|
||||
|| !TextUtils.equals(clientPackageName, selectedRoute.getClientPackageName())) {
|
||||
Log.w(TAG, "Ignoring route selection which has non-matching clientPackageName.");
|
||||
return;
|
||||
}
|
||||
|
||||
MediaRouter2ServiceImpl service = mServiceRef.get();
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Client2Record clientRecord;
|
||||
synchronized (service.mLock) {
|
||||
clientRecord = mUserRecord.findClientRecordLocked(clientPackageName);
|
||||
}
|
||||
|
||||
//TODO: handle a case such that controlHints is null. (How should we notify MR2?)
|
||||
|
||||
if (clientRecord.mSelectingRoute == null || !TextUtils.equals(
|
||||
clientRecord.mSelectingRoute.getUniqueId(), selectedRoute.getUniqueId())) {
|
||||
Log.w(TAG, "Ignoring invalid updateSelectedRoute call. selectingRoute="
|
||||
+ clientRecord.mSelectingRoute + " route=" + selectedRoute);
|
||||
unselectRoute(clientPackageName, selectedRoute);
|
||||
return;
|
||||
}
|
||||
clientRecord.mSelectingRoute = null;
|
||||
clientRecord.mSelectedRoute = selectedRoute;
|
||||
|
||||
notifyRouteSelectedToClient(clientRecord.mClient,
|
||||
selectedRoute,
|
||||
clientRecord.mIsManagerSelecting
|
||||
? MediaRouter2.SELECT_REASON_SYSTEM_SELECTED :
|
||||
MediaRouter2.SELECT_REASON_USER_SELECTED,
|
||||
controlHints);
|
||||
updateClientUsage(clientRecord);
|
||||
|
||||
// Remove the fallback route selection message.
|
||||
removeMessages(seq);
|
||||
}
|
||||
|
||||
private void handleRouteSelectionTimeout(String clientPackageName,
|
||||
MediaRoute2Info selectingRoute) {
|
||||
MediaRouter2ServiceImpl service = mServiceRef.get();
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Client2Record clientRecord;
|
||||
synchronized (service.mLock) {
|
||||
clientRecord = mUserRecord.findClientRecordLocked(clientPackageName);
|
||||
}
|
||||
|
||||
if (clientRecord == null) {
|
||||
Log.w(TAG, "The client has gone. packageName=" + clientPackageName
|
||||
+ " selectingRoute=" + selectingRoute);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clientRecord.mSelectingRoute == null || !TextUtils.equals(
|
||||
clientRecord.mSelectingRoute.getUniqueId(), selectingRoute.getUniqueId())) {
|
||||
Log.w(TAG, "Ignoring invalid selectFallbackRoute call. "
|
||||
+ "Current selectingRoute=" + clientRecord.mSelectingRoute
|
||||
+ " , original selectingRoute=" + selectingRoute);
|
||||
return;
|
||||
}
|
||||
|
||||
clientRecord.mSelectingRoute = null;
|
||||
// TODO: When the default route is introduced, make mSelectedRoute always non-null.
|
||||
MediaRoute2Info fallbackRoute = null;
|
||||
clientRecord.mSelectedRoute = fallbackRoute;
|
||||
|
||||
notifyRouteSelectedToClient(clientRecord.mClient,
|
||||
fallbackRoute,
|
||||
MediaRouter2.SELECT_REASON_FALLBACK,
|
||||
Bundle.EMPTY /* controlHints */);
|
||||
updateClientUsage(clientRecord);
|
||||
}
|
||||
|
||||
private void requestSelectRoute(String clientPackageName, MediaRoute2Info route, int seq) {
|
||||
if (route != null) {
|
||||
MediaRoute2Provider provider = findProvider(route.getProviderId());
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Ignoring to select route of unknown provider " + route);
|
||||
} else {
|
||||
provider.requestSelectRoute(clientPackageName, route.getId(), seq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unselectRoute(String clientPackageName, MediaRoute2Info route) {
|
||||
if (route != null) {
|
||||
MediaRoute2Provider provider = findProvider(route.getProviderId());
|
||||
if (provider == null) {
|
||||
Slog.w(TAG, "Ignoring to unselect route of unknown provider " + route);
|
||||
} else {
|
||||
provider.unselectRoute(clientPackageName, route.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendControlRequest(MediaRoute2Info route, Intent request) {
|
||||
final MediaRoute2Provider provider = findProvider(route.getProviderId());
|
||||
if (provider != null) {
|
||||
|
||||
@@ -487,11 +487,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
|
||||
|
||||
// Binder call
|
||||
@Override
|
||||
public void selectClientRoute2(IMediaRouter2Manager manager,
|
||||
String packageName, MediaRoute2Info route) {
|
||||
mService2.selectClientRoute2(manager, packageName, route);
|
||||
public void requestCreateClientSession(IMediaRouter2Manager manager, String packageName,
|
||||
MediaRoute2Info route, int requestId) {
|
||||
mService2.requestCreateClientSession(manager, packageName, route, requestId);
|
||||
}
|
||||
|
||||
// Binder call
|
||||
@Override
|
||||
public void setControlCategories(IMediaRouter2Client client, List<String> categories) {
|
||||
|
||||
@@ -94,21 +94,24 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
//TODO: implement method
|
||||
@Override
|
||||
public void requestSelectRoute(@NonNull String packageName, @NonNull String routeId, int seq) {
|
||||
try {
|
||||
mAudioService.setBluetoothA2dpOn(
|
||||
!TextUtils.equals(routeId, mDefaultRoute.getId()));
|
||||
} catch (RemoteException ex) {
|
||||
Log.e(TAG, "Error changing Bluetooth A2DP route");
|
||||
}
|
||||
public void releaseSession(int sessionId) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
//TODO: implement method
|
||||
@Override
|
||||
public void unselectRoute(@NonNull String packageName, @NonNull String routeId) {
|
||||
// does nothing..?
|
||||
public void addRoute(int sessionId, MediaRoute2Info route) {
|
||||
//TODO: implement method
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRoute(int sessionId, MediaRoute2Info route) {
|
||||
//TODO: implement method
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferRoute(int sessionId, MediaRoute2Info route) {
|
||||
//TODO: implement method
|
||||
}
|
||||
|
||||
//TODO: implement method
|
||||
|
||||
Reference in New Issue
Block a user