Merge "[Bugfix][Media] Fix ISessionControllerCallback leaks in the system_server when the far side died"

This commit is contained in:
Kevin Rocard
2022-02-24 10:38:36 +00:00
committed by Gerrit Code Review

View File

@@ -62,6 +62,7 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.NoSuchElementException;
/** /**
* This is the system implementation of a Session. Apps will interact with the * This is the system implementation of a Session. Apps will interact with the
@@ -792,7 +793,10 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
} }
for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) { for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
try { try {
holder.mCallback.asBinder().unlinkToDeath(holder.mDeathMonitor, 0);
holder.mCallback.onSessionDestroyed(); holder.mCallback.onSessionDestroyed();
} catch (NoSuchElementException e) {
logCallbackException("error unlinking to binder death", holder, e);
} catch (DeadObjectException e) { } catch (DeadObjectException e) {
logCallbackException("Removing dead callback in pushSessionDestroyed", holder, e); logCallbackException("Removing dead callback in pushSessionDestroyed", holder, e);
} catch (RemoteException e) { } catch (RemoteException e) {
@@ -1375,12 +1379,22 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
return; return;
} }
if (getControllerHolderIndexForCb(cb) < 0) { if (getControllerHolderIndexForCb(cb) < 0) {
mControllerCallbackHolders.add(new ISessionControllerCallbackHolder(cb, ISessionControllerCallbackHolder holder = new ISessionControllerCallbackHolder(
packageName, Binder.getCallingUid())); cb, packageName, Binder.getCallingUid(), () -> unregisterCallback(cb));
mControllerCallbackHolders.add(holder);
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "registering controller callback " + cb + " from controller" Log.d(TAG, "registering controller callback " + cb + " from controller"
+ packageName); + packageName);
} }
// Avoid callback leaks
try {
// cb is not referenced outside of the MediaSessionRecord, so the death
// handler won't prevent MediaSessionRecord to be garbage collected.
cb.asBinder().linkToDeath(holder.mDeathMonitor, 0);
} catch (RemoteException e) {
unregisterCallback(cb);
Log.w(TAG, "registerCallback failed to linkToDeath", e);
}
} }
} }
} }
@@ -1390,6 +1404,12 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
synchronized (mLock) { synchronized (mLock) {
int index = getControllerHolderIndexForCb(cb); int index = getControllerHolderIndexForCb(cb);
if (index != -1) { if (index != -1) {
try {
cb.asBinder().unlinkToDeath(
mControllerCallbackHolders.get(index).mDeathMonitor, 0);
} catch (NoSuchElementException e) {
Log.w(TAG, "error unlinking to binder death", e);
}
mControllerCallbackHolders.remove(index); mControllerCallbackHolders.remove(index);
} }
if (DEBUG) { if (DEBUG) {
@@ -1600,12 +1620,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
private final ISessionControllerCallback mCallback; private final ISessionControllerCallback mCallback;
private final String mPackageName; private final String mPackageName;
private final int mUid; private final int mUid;
private final IBinder.DeathRecipient mDeathMonitor;
ISessionControllerCallbackHolder(ISessionControllerCallback callback, String packageName, ISessionControllerCallbackHolder(ISessionControllerCallback callback, String packageName,
int uid) { int uid, IBinder.DeathRecipient deathMonitor) {
mCallback = callback; mCallback = callback;
mPackageName = packageName; mPackageName = packageName;
mUid = uid; mUid = uid;
mDeathMonitor = deathMonitor;
} }
} }