Fix missing notification of session service release
PiperOrigin-RevId: 422352302
This commit is contained in:
parent
3cfd24a912
commit
9f2f33657f
@ -45,8 +45,11 @@ import androidx.media3.common.util.Log;
|
|||||||
import androidx.media3.session.MediaSession.ControllerInfo;
|
import androidx.media3.session.MediaSession.ControllerInfo;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Superclass to be extended by services hosting {@link MediaSession media sessions}.
|
* Superclass to be extended by services hosting {@link MediaSession media sessions}.
|
||||||
@ -417,30 +420,42 @@ public abstract class MediaSessionService extends Service {
|
|||||||
private final WeakReference<MediaSessionService> serviceReference;
|
private final WeakReference<MediaSessionService> serviceReference;
|
||||||
private final Handler handler;
|
private final Handler handler;
|
||||||
private final MediaSessionManager mediaSessionManager;
|
private final MediaSessionManager mediaSessionManager;
|
||||||
|
private final Set<IMediaController> pendingControllers;
|
||||||
|
|
||||||
public MediaSessionServiceStub(MediaSessionService serviceReference) {
|
public MediaSessionServiceStub(MediaSessionService serviceReference) {
|
||||||
this.serviceReference = new WeakReference<>(serviceReference);
|
this.serviceReference = new WeakReference<>(serviceReference);
|
||||||
Context context = serviceReference.getApplicationContext();
|
Context context = serviceReference.getApplicationContext();
|
||||||
handler = new Handler(context.getMainLooper());
|
handler = new Handler(context.getMainLooper());
|
||||||
mediaSessionManager = MediaSessionManager.getSessionManager(context);
|
mediaSessionManager = MediaSessionManager.getSessionManager(context);
|
||||||
|
pendingControllers = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connect(
|
public void connect(
|
||||||
@Nullable IMediaController caller, @Nullable Bundle connectionRequestBundle) {
|
@Nullable IMediaController caller, @Nullable Bundle connectionRequestBundle) {
|
||||||
if (caller == null || connectionRequestBundle == null) {
|
if (caller == null || connectionRequestBundle == null) {
|
||||||
return;
|
// Malformed call from potentially malicious controller.
|
||||||
}
|
// No need to notify that we're ignoring call.
|
||||||
if (serviceReference.get() == null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ConnectionRequest request;
|
ConnectionRequest request;
|
||||||
try {
|
try {
|
||||||
request = ConnectionRequest.CREATOR.fromBundle(connectionRequestBundle);
|
request = ConnectionRequest.CREATOR.fromBundle(connectionRequestBundle);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
// Malformed call from potentially malicious controller.
|
||||||
|
// No need to notify that we're ignoring call.
|
||||||
Log.w(TAG, "Ignoring malformed Bundle for ConnectionRequest", e);
|
Log.w(TAG, "Ignoring malformed Bundle for ConnectionRequest", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (serviceReference.get() == null) {
|
||||||
|
try {
|
||||||
|
caller.onDisconnected(/* seq= */ 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Controller may be died prematurely.
|
||||||
|
// Not an issue because we'll ignore it anyway.
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
int callingPid = Binder.getCallingPid();
|
int callingPid = Binder.getCallingPid();
|
||||||
int uid = Binder.getCallingUid();
|
int uid = Binder.getCallingUid();
|
||||||
long token = Binder.clearCallingIdentity();
|
long token = Binder.clearCallingIdentity();
|
||||||
@ -448,19 +463,17 @@ public abstract class MediaSessionService extends Service {
|
|||||||
MediaSessionManager.RemoteUserInfo remoteUserInfo =
|
MediaSessionManager.RemoteUserInfo remoteUserInfo =
|
||||||
new MediaSessionManager.RemoteUserInfo(request.packageName, pid, uid);
|
new MediaSessionManager.RemoteUserInfo(request.packageName, pid, uid);
|
||||||
boolean isTrusted = mediaSessionManager.isTrustedForMediaControl(remoteUserInfo);
|
boolean isTrusted = mediaSessionManager.isTrustedForMediaControl(remoteUserInfo);
|
||||||
|
pendingControllers.add(caller);
|
||||||
try {
|
try {
|
||||||
handler.post(
|
handler.post(
|
||||||
() -> {
|
() -> {
|
||||||
|
pendingControllers.remove(caller);
|
||||||
boolean shouldNotifyDisconnected = true;
|
boolean shouldNotifyDisconnected = true;
|
||||||
try {
|
try {
|
||||||
@Nullable MediaSessionService service = serviceReference.get();
|
@Nullable MediaSessionService service = serviceReference.get();
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (service == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerInfo controllerInfo =
|
ControllerInfo controllerInfo =
|
||||||
new ControllerInfo(
|
new ControllerInfo(
|
||||||
remoteUserInfo,
|
remoteUserInfo,
|
||||||
@ -510,6 +523,13 @@ public abstract class MediaSessionService extends Service {
|
|||||||
public void release() {
|
public void release() {
|
||||||
serviceReference.clear();
|
serviceReference.clear();
|
||||||
handler.removeCallbacksAndMessages(null);
|
handler.removeCallbacksAndMessages(null);
|
||||||
|
for (IMediaController controller : pendingControllers) {
|
||||||
|
try {
|
||||||
|
controller.onDisconnected(/* seq= */ 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Ignore. We're releasing.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user