From 9f2f33657f9d76dc88a689dff7a2d26948bb8575 Mon Sep 17 00:00:00 2001 From: jaewan Date: Mon, 17 Jan 2022 14:23:48 +0000 Subject: [PATCH] Fix missing notification of session service release PiperOrigin-RevId: 422352302 --- .../media3/session/MediaSessionService.java | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java b/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java index 148d616a64..9a380b0464 100644 --- a/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java +++ b/libraries/session/src/main/java/androidx/media3/session/MediaSessionService.java @@ -45,8 +45,11 @@ import androidx.media3.common.util.Log; import androidx.media3.session.MediaSession.ControllerInfo; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; /** * Superclass to be extended by services hosting {@link MediaSession media sessions}. @@ -417,30 +420,42 @@ public abstract class MediaSessionService extends Service { private final WeakReference serviceReference; private final Handler handler; private final MediaSessionManager mediaSessionManager; + private final Set pendingControllers; public MediaSessionServiceStub(MediaSessionService serviceReference) { this.serviceReference = new WeakReference<>(serviceReference); Context context = serviceReference.getApplicationContext(); handler = new Handler(context.getMainLooper()); mediaSessionManager = MediaSessionManager.getSessionManager(context); + pendingControllers = Collections.newSetFromMap(new ConcurrentHashMap<>()); } @Override public void connect( @Nullable IMediaController caller, @Nullable Bundle connectionRequestBundle) { if (caller == null || connectionRequestBundle == null) { - return; - } - if (serviceReference.get() == null) { + // Malformed call from potentially malicious controller. + // No need to notify that we're ignoring call. return; } ConnectionRequest request; try { request = ConnectionRequest.CREATOR.fromBundle(connectionRequestBundle); } 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); 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 uid = Binder.getCallingUid(); long token = Binder.clearCallingIdentity(); @@ -448,19 +463,17 @@ public abstract class MediaSessionService extends Service { MediaSessionManager.RemoteUserInfo remoteUserInfo = new MediaSessionManager.RemoteUserInfo(request.packageName, pid, uid); boolean isTrusted = mediaSessionManager.isTrustedForMediaControl(remoteUserInfo); + pendingControllers.add(caller); try { handler.post( () -> { + pendingControllers.remove(caller); boolean shouldNotifyDisconnected = true; try { @Nullable MediaSessionService service = serviceReference.get(); if (service == null) { return; } - if (service == null) { - return; - } - ControllerInfo controllerInfo = new ControllerInfo( remoteUserInfo, @@ -510,6 +523,13 @@ public abstract class MediaSessionService extends Service { public void release() { serviceReference.clear(); handler.removeCallbacksAndMessages(null); + for (IMediaController controller : pendingControllers) { + try { + controller.onDisconnected(/* seq= */ 0); + } catch (RemoteException e) { + // Ignore. We're releasing. + } + } } } }