Merge "MediaRouter2: Release controller when transfer result arrives" into rvc-dev

This commit is contained in:
Hyundo Moon
2020-04-23 11:27:16 +00:00
committed by Android (Google) Code Review

View File

@@ -35,7 +35,6 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -379,11 +378,7 @@ public final class MediaRouter2 {
*/ */
public void transferTo(@NonNull MediaRoute2Info route) { public void transferTo(@NonNull MediaRoute2Info route) {
Objects.requireNonNull(route, "route must not be null"); Objects.requireNonNull(route, "route must not be null");
transfer(getCurrentController(), route);
List<RoutingController> controllers = getControllers();
RoutingController controller = controllers.get(controllers.size() - 1);
transfer(controller, route);
} }
/** /**
@@ -391,10 +386,7 @@ public final class MediaRouter2 {
* controls the media routing, this method is a no-op. * controls the media routing, this method is a no-op.
*/ */
public void stop() { public void stop() {
List<RoutingController> controllers = getControllers(); getCurrentController().release();
RoutingController controller = controllers.get(controllers.size() - 1);
controller.release();
} }
/** /**
@@ -417,12 +409,9 @@ public final class MediaRouter2 {
return; return;
} }
controller.release();
final int requestId = mControllerCreationRequestCnt.getAndIncrement(); final int requestId = mControllerCreationRequestCnt.getAndIncrement();
ControllerCreationRequest request = ControllerCreationRequest request = new ControllerCreationRequest(requestId, route);
new ControllerCreationRequest(requestId, controller, route);
mControllerCreationRequests.add(request); mControllerCreationRequests.add(request);
OnGetControllerHintsListener listener = mOnGetControllerHintsListener; OnGetControllerHintsListener listener = mOnGetControllerHintsListener;
@@ -450,6 +439,12 @@ public final class MediaRouter2 {
} }
} }
@NonNull
private RoutingController getCurrentController() {
List<RoutingController> controllers = getControllers();
return controllers.get(controllers.size() - 1);
}
/** /**
* Gets a {@link RoutingController} which can control the routes provided by system. * Gets a {@link RoutingController} which can control the routes provided by system.
* e.g. Phone speaker, wired headset, Bluetooth, etc. * e.g. Phone speaker, wired headset, Bluetooth, etc.
@@ -474,13 +469,8 @@ public final class MediaRouter2 {
public List<RoutingController> getControllers() { public List<RoutingController> getControllers() {
List<RoutingController> result = new ArrayList<>(); List<RoutingController> result = new ArrayList<>();
result.add(0, mSystemController); result.add(0, mSystemController);
Collection<RoutingController> controllers;
synchronized (sRouterLock) { synchronized (sRouterLock) {
controllers = mRoutingControllers.values(); result.addAll(mRoutingControllers.values());
if (controllers != null) {
result.addAll(controllers);
}
} }
return result; return result;
} }
@@ -608,19 +598,33 @@ public final class MediaRouter2 {
} }
} }
if (sessionInfo != null) { if (sessionInfo == null) {
return;
}
RoutingController oldController = getCurrentController();
if (!oldController.releaseInternal(
/* shouldReleaseSession= */ true, /* shouldNotifyStop= */ false)) {
// Could not release the controller since it was just released by other thread.
oldController = getSystemController();
}
RoutingController newController; RoutingController newController;
if (sessionInfo.isSystemSession()) { if (sessionInfo.isSystemSession()) {
newController = getSystemController(); newController = getSystemController();
newController.setRoutingSessionInfo(sessionInfo);
} else { } else {
newController = new RoutingController(sessionInfo); newController = new RoutingController(sessionInfo);
synchronized (sRouterLock) { synchronized (sRouterLock) {
mRoutingControllers.put(newController.getId(), newController); mRoutingControllers.put(newController.getId(), newController);
} }
} }
//TODO: Determine oldController properly when transfer is launched by Output Switcher.
notifyTransfer(matchingRequest != null ? matchingRequest.mController : // Two controller can be same if stop() is called before the result of Cast -> Phone comes.
getSystemController(), newController); if (oldController != newController) {
notifyTransfer(oldController, newController);
} else if (matchingRequest != null) {
notifyTransferFailure(matchingRequest.mRoute);
} }
} }
@@ -687,7 +691,8 @@ public final class MediaRouter2 {
return; return;
} }
matchingController.releaseInternal(/* shouldReleaseSession= */ false); matchingController.releaseInternal(
/* shouldReleaseSession= */ false, /* shouldNotifyStop= */ true);
} }
void onGetControllerHintsForCreatingSessionOnHandler(long uniqueRequestId, void onGetControllerHintsForCreatingSessionOnHandler(long uniqueRequestId,
@@ -814,8 +819,9 @@ public final class MediaRouter2 {
public abstract static class TransferCallback { public abstract static class TransferCallback {
/** /**
* Called when a media is transferred between two different routing controllers. * Called when a media is transferred between two different routing controllers.
* This can happen by calling {@link #transferTo(MediaRoute2Info)} or * This can happen by calling {@link #transferTo(MediaRoute2Info)}.
* {@link RoutingController#release()}. * The {@code oldController} is released before this method is called, except for the
* {@link #getSystemController() system controller}.
* *
* @param oldController the previous controller that controlled routing * @param oldController the previous controller that controlled routing
* @param newController the new controller to control routing * @param newController the new controller to control routing
@@ -833,6 +839,9 @@ public final class MediaRouter2 {
/** /**
* Called when a media routing stops. It can be stopped by a user or a provider. * Called when a media routing stops. It can be stopped by a user or a provider.
* App should not continue playing media locally when this method is called.
* The {@code oldController} is released before this method is called, except for the
* {@link #getSystemController() system controller}.
* *
* @param controller the controller that controlled the stopped media routing. * @param controller the controller that controlled the stopped media routing.
*/ */
@@ -1206,14 +1215,18 @@ public final class MediaRouter2 {
*/ */
// TODO: Add tests using {@link MediaRouter2Manager#getActiveSessions()}. // TODO: Add tests using {@link MediaRouter2Manager#getActiveSessions()}.
public void release() { public void release() {
releaseInternal(/* shouldReleaseSession= */ true); releaseInternal(/* shouldReleaseSession= */ true, /* shouldNotifyStop= */ true);
} }
void releaseInternal(boolean shouldReleaseSession) { /**
* Returns {@code true} when succeeded to release, {@code false} if the controller is
* already released.
*/
boolean releaseInternal(boolean shouldReleaseSession, boolean shouldNotifyStop) {
synchronized (mControllerLock) { synchronized (mControllerLock) {
if (mIsReleased) { if (mIsReleased) {
Log.w(TAG, "releaseInternal() called on released controller. Ignoring."); Log.w(TAG, "releaseInternal() called on released controller. Ignoring.");
return; return false;
} }
mIsReleased = true; mIsReleased = true;
} }
@@ -1232,12 +1245,11 @@ public final class MediaRouter2 {
} }
} }
if (Thread.currentThread() == mHandler.getLooper().getThread()) { if (shouldNotifyStop) {
notifyStop(this);
} else {
mHandler.sendMessage(obtainMessage(MediaRouter2::notifyStop, MediaRouter2.this, mHandler.sendMessage(obtainMessage(MediaRouter2::notifyStop, MediaRouter2.this,
RoutingController.this)); RoutingController.this));
} }
return true;
} }
@Override @Override
@@ -1294,13 +1306,14 @@ public final class MediaRouter2 {
} }
@Override @Override
public void release() { public boolean isReleased() {
// Do nothing. SystemRoutingController will never be released // SystemRoutingController will never be released
return false;
} }
@Override @Override
public boolean isReleased() { boolean releaseInternal(boolean shouldReleaseSession, boolean shouldNotifyStop) {
// SystemRoutingController will never be released // Do nothing. SystemRoutingController will never be released
return false; return false;
} }
} }
@@ -1391,13 +1404,10 @@ public final class MediaRouter2 {
static final class ControllerCreationRequest { static final class ControllerCreationRequest {
public final int mRequestId; public final int mRequestId;
public final RoutingController mController;
public final MediaRoute2Info mRoute; public final MediaRoute2Info mRoute;
ControllerCreationRequest(int requestId, @NonNull RoutingController controller, ControllerCreationRequest(int requestId, @NonNull MediaRoute2Info route) {
@NonNull MediaRoute2Info route) {
mRequestId = requestId; mRequestId = requestId;
mController = controller;
mRoute = route; mRoute = route;
} }
} }