Handle disconnection of MediaSession2/Controller2

Bug: 122055262
Test: build
Change-Id: I388ab76beb8fc41b47e8f6310cc0bcb79b6acc9f
This commit is contained in:
Sungsoo Lim
2018-12-31 09:38:40 +09:00
parent 4c4d22265d
commit cfd36a5ab5
3 changed files with 86 additions and 24 deletions

View File

@@ -21,6 +21,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import java.util.Objects;
/**
* Handles incoming commands from {@link MediaSession2} and {@link MediaLibrarySession}
* to both {@link MediaController2} and {@link MediaBrowser2}.
@@ -68,6 +70,20 @@ public final class Controller2Link implements Parcelable {
dest.writeStrongBinder(mIController.asBinder());
}
@Override
public int hashCode() {
return mIController.asBinder().hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Controller2Link)) {
return false;
}
Controller2Link other = (Controller2Link) obj;
return Objects.equals(mIController.asBinder(), other.mIController.asBinder());
}
/** Interface method for IMediaController2.notifyConnected */
public void notifyConnected(int seq, Bundle connectionResult) {
try {

View File

@@ -98,7 +98,6 @@ public class MediaController2 implements AutoCloseable {
mNextSeqNumber = 0;
Session2Link sessionBinder = token.getSessionLink();
if (token.getType() == TYPE_SESSION) {
connectToSession();
} else {
@@ -120,9 +119,11 @@ public class MediaController2 implements AutoCloseable {
mCallbackExecutor.execute(() -> {
mCallback.onDisconnected(MediaController2.this);
});
mSessionBinder = null;
}
}
// Called by Controller2Link.onConnected
void onConnected(int seq, Bundle connectionResult) {
final long token = Binder.clearCallingIdentity();
try {
@@ -155,10 +156,18 @@ public class MediaController2 implements AutoCloseable {
}
}
// Called by Controller2Link.onDisconnected
void onDisconnected(int seq) {
// TODO: Implement this
final long token = Binder.clearCallingIdentity();
try {
// close() will call mCallback.onDisconnected
close();
} finally {
Binder.restoreCallingIdentity(token);
}
}
// Called by Controller2Link.onSessionCommand
void onSessionCommand(int seq, Session2Command command, Bundle args) {
// TODO: Implement this
}

View File

@@ -35,6 +35,7 @@ import android.os.Process;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -107,7 +108,13 @@ public class MediaSession2 implements AutoCloseable {
synchronized (MediaSession2.class) {
SESSION_ID_LIST.remove(mSessionId);
}
// TODO: Implement this
Collection<ControllerInfo> controllerInfos;
synchronized (mLock) {
controllerInfos = mConnectedControllers.values();
}
for (ControllerInfo info : controllerInfos) {
info.notifyDisconnected();
}
} catch (Exception e) {
// Should not be here.
}
@@ -118,6 +125,7 @@ public class MediaSession2 implements AutoCloseable {
return true;
}
// Called by Session2Link.onConnect
void onConnect(final Controller2Link controller, int seq, Bundle connectionRequest) {
if (controller == null || connectionRequest == null) {
return;
@@ -173,21 +181,12 @@ public class MediaSession2 implements AutoCloseable {
if (isClosed()) {
return;
}
try {
controller.notifyConnected(
controllerInfo.mNextSeqNumber++, connectionResult);
} catch (RuntimeException e) {
// Controller may be died prematurely.
}
controllerInfo.notifyConnected(connectionResult);
} else {
if (DEBUG) {
Log.d(TAG, "Rejecting connection, controllerInfo=" + controllerInfo);
}
try {
controller.notifyDisconnected(controllerInfo.mNextSeqNumber++);
} catch (RuntimeException e) {
// Controller may be died prematurely.
}
controllerInfo.notifyDisconnected();
}
});
} finally {
@@ -195,20 +194,24 @@ public class MediaSession2 implements AutoCloseable {
}
}
// Called by Session2Link.onDisconnect
void onDisconnect(final Controller2Link controller, int seq) {
if (controller == null) {
return;
}
final ControllerInfo controllerInfo;
synchronized (mLock) {
controllerInfo = mConnectedControllers.get(controller);
}
if (controllerInfo == null) {
return;
}
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
final ControllerInfo controllerInfo = mConnectedControllers.get(controller);
mCallbackExecutor.execute(() -> {
try {
controller.notifyDisconnected(controllerInfo.mNextSeqNumber++);
} catch (RuntimeException e) {
// Controller may be died prematurely.
}
mCallback.onDisconnected(MediaSession2.this, controllerInfo);
});
mConnectedControllers.remove(controller);
}
@@ -217,6 +220,7 @@ public class MediaSession2 implements AutoCloseable {
}
}
// Called by Session2Link.onSessionCommand
void onSessionCommand(final Controller2Link controller, final int seq,
final Session2Command command, final Bundle args) {
// TODO: Implement this
@@ -323,13 +327,12 @@ public class MediaSession2 implements AutoCloseable {
* <p>
* This API is not generally intended for third party application developers.
*/
public static final class ControllerInfo {
static final class ControllerInfo {
private final RemoteUserInfo mRemoteUserInfo;
private final boolean mIsTrusted;
private final Controller2Link mControllerBinder;
private int mNextSeqNumber;
@SuppressWarnings("WeakerAccess") /* synthetic access */
int mNextSeqNumber;
@SuppressWarnings("WeakerAccess") /* synthetic access */
Session2CommandGroup mAllowedCommands;
@@ -348,7 +351,7 @@ public class MediaSession2 implements AutoCloseable {
}
/**
* @hide
* @return remote user info of the controller.
*/
@NonNull
public RemoteUserInfo getRemoteUserInfo() {
@@ -370,6 +373,36 @@ public class MediaSession2 implements AutoCloseable {
return mRemoteUserInfo.getUid();
}
public void notifyConnected(Bundle connectionResult) {
if (mControllerBinder != null) {
try {
mControllerBinder.notifyConnected(getNextSeqNumber(), connectionResult);
} catch (RuntimeException e) {
// Controller may be died prematurely.
}
}
}
public void notifyDisconnected() {
if (mControllerBinder != null) {
try {
mControllerBinder.notifyDisconnected(getNextSeqNumber());
} catch (RuntimeException e) {
// Controller may be died prematurely.
}
}
}
public void sendSessionCommand(Session2Command command, Bundle args) {
if (mControllerBinder != null) {
try {
mControllerBinder.sendSessionCommand(getNextSeqNumber(), command, args);
} catch (RuntimeException e) {
// Controller may be died prematurely.
}
}
}
/**
* Return if the controller has granted {@code android.permission.MEDIA_CONTENT_CONTROL} or
* has a enabled notification listener so can be trusted to accept connection and incoming
@@ -407,6 +440,10 @@ public class MediaSession2 implements AutoCloseable {
return "ControllerInfo {pkg=" + mRemoteUserInfo.getPackageName() + ", uid="
+ mRemoteUserInfo.getUid() + ", allowedCommands=" + mAllowedCommands + "})";
}
private synchronized int getNextSeqNumber() {
return mNextSeqNumber++;
}
}
/**