Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b92cea9b authored by Santiago Seifert's avatar Santiago Seifert Committed by Gerrit Code Review
Browse files

Merge "Simplify MediaSessionRecord callback invocations" into main

parents 51e8133d b1b6f7f3
Loading
Loading
Loading
Loading
+54 −151
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -85,7 +84,6 @@ import com.android.server.uri.UriGrantsManagerInternal;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -183,6 +181,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
    private final boolean mVolumeAdjustmentForRemoteGroupSessions;

    private final Object mLock = new Object();
    // This field is partially guarded by mLock. Writes and non-atomic iterations (for example:
    // index-based-iterations) must be guarded by mLock. But it is safe to acquire an iterator
    // without acquiring mLock.
    private final CopyOnWriteArrayList<ISessionControllerCallbackHolder>
            mControllerCallbackHolders = new CopyOnWriteArrayList<>();

@@ -770,24 +771,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
            }
            playbackState = mPlaybackState;
        }
        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
            try {
                holder.mCallback.onPlaybackStateChanged(playbackState);
            } catch (DeadObjectException e) {
                if (deadCallbackHolders == null) {
                    deadCallbackHolders = new ArrayList<>();
                }
                deadCallbackHolders.add(holder);
                logCallbackException("Removing dead callback in pushPlaybackStateUpdate", holder,
                        e);
            } catch (RemoteException e) {
                logCallbackException("unexpected exception in pushPlaybackStateUpdate", holder, e);
            }
        }
        if (deadCallbackHolders != null) {
            removeControllerHoldersSafely(deadCallbackHolders);
        }
        performOnCallbackHolders(
                "pushPlaybackStateUpdate",
                holder -> holder.mCallback.onPlaybackStateChanged(playbackState));
    }

    private void pushMetadataUpdate() {
@@ -798,23 +784,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
            }
            metadata = mMetadata;
        }
        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
            try {
                holder.mCallback.onMetadataChanged(metadata);
            } catch (DeadObjectException e) {
                if (deadCallbackHolders == null) {
                    deadCallbackHolders = new ArrayList<>();
                }
                deadCallbackHolders.add(holder);
                logCallbackException("Removing dead callback in pushMetadataUpdate", holder, e);
            } catch (RemoteException e) {
                logCallbackException("unexpected exception in pushMetadataUpdate", holder, e);
            }
        }
        if (deadCallbackHolders != null) {
            removeControllerHoldersSafely(deadCallbackHolders);
        }
        performOnCallbackHolders(
                "pushMetadataUpdate", holder -> holder.mCallback.onMetadataChanged(metadata));
    }

    private void pushQueueUpdate() {
@@ -825,8 +796,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
            }
            toSend = mQueue == null ? null : new ArrayList<>(mQueue);
        }
        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
        performOnCallbackHolders(
                "pushQueueUpdate",
                holder -> {
                    ParceledListSlice<QueueItem> parcelableQueue = null;
                    if (toSend != null) {
                        parcelableQueue = new ParceledListSlice<>(toSend);
@@ -834,22 +806,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
                        // as onQueueChanged is an async binder call.
                        parcelableQueue.setInlineCountLimit(1);
                    }

            try {
                    holder.mCallback.onQueueChanged(parcelableQueue);
            } catch (DeadObjectException e) {
                if (deadCallbackHolders == null) {
                    deadCallbackHolders = new ArrayList<>();
                }
                deadCallbackHolders.add(holder);
                logCallbackException("Removing dead callback in pushQueueUpdate", holder, e);
            } catch (RemoteException e) {
                logCallbackException("unexpected exception in pushQueueUpdate", holder, e);
            }
        }
        if (deadCallbackHolders != null) {
            removeControllerHoldersSafely(deadCallbackHolders);
        }
                });
    }

    private void pushQueueTitleUpdate() {
@@ -860,23 +818,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
            }
            queueTitle = mQueueTitle;
        }
        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
            try {
                holder.mCallback.onQueueTitleChanged(queueTitle);
            } catch (DeadObjectException e) {
                if (deadCallbackHolders == null) {
                    deadCallbackHolders = new ArrayList<>();
                }
                deadCallbackHolders.add(holder);
                logCallbackException("Removing dead callback in pushQueueTitleUpdate", holder, e);
            } catch (RemoteException e) {
                logCallbackException("unexpected exception in pushQueueTitleUpdate", holder, e);
            }
        }
        if (deadCallbackHolders != null) {
            removeControllerHoldersSafely(deadCallbackHolders);
        }
        performOnCallbackHolders(
                "pushQueueTitleUpdate", holder -> holder.mCallback.onQueueTitleChanged(queueTitle));
    }

    private void pushExtrasUpdate() {
@@ -887,23 +830,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
            }
            extras = mExtras;
        }
        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
            try {
                holder.mCallback.onExtrasChanged(extras);
            } catch (DeadObjectException e) {
                if (deadCallbackHolders == null) {
                    deadCallbackHolders = new ArrayList<>();
                }
                deadCallbackHolders.add(holder);
                logCallbackException("Removing dead callback in pushExtrasUpdate", holder, e);
            } catch (RemoteException e) {
                logCallbackException("unexpected exception in pushExtrasUpdate", holder, e);
            }
        }
        if (deadCallbackHolders != null) {
            removeControllerHoldersSafely(deadCallbackHolders);
        }
        performOnCallbackHolders(
                "pushExtrasUpdate", holder -> holder.mCallback.onExtrasChanged(extras));
    }

    private void pushVolumeUpdate() {
@@ -914,23 +842,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
            }
            info = getVolumeAttributes();
        }
        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
            try {
                holder.mCallback.onVolumeInfoChanged(info);
            } catch (DeadObjectException e) {
                if (deadCallbackHolders == null) {
                    deadCallbackHolders = new ArrayList<>();
                }
                deadCallbackHolders.add(holder);
                logCallbackException("Removing dead callback in pushVolumeUpdate", holder, e);
            } catch (RemoteException e) {
                logCallbackException("unexpected exception in pushVolumeUpdate", holder, e);
            }
        }
        if (deadCallbackHolders != null) {
            removeControllerHoldersSafely(deadCallbackHolders);
        }
        performOnCallbackHolders(
                "pushVolumeUpdate", holder -> holder.mCallback.onVolumeInfoChanged(info));
    }

    private void pushEvent(String event, Bundle data) {
@@ -939,23 +852,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
                return;
            }
        }
        Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
            try {
                holder.mCallback.onEvent(event, data);
            } catch (DeadObjectException e) {
                if (deadCallbackHolders == null) {
                    deadCallbackHolders = new ArrayList<>();
                }
                deadCallbackHolders.add(holder);
                logCallbackException("Removing dead callback in pushEvent", holder, e);
            } catch (RemoteException e) {
                logCallbackException("unexpected exception in pushEvent", holder, e);
            }
        }
        if (deadCallbackHolders != null) {
            removeControllerHoldersSafely(deadCallbackHolders);
        }
        performOnCallbackHolders("pushEvent", holder -> holder.mCallback.onEvent(event, data));
    }

    private void pushSessionDestroyed() {
@@ -966,20 +863,37 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
                return;
            }
        }
        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
            try {
        performOnCallbackHolders(
                "pushSessionDestroyed",
                holder -> {
                    holder.mCallback.asBinder().unlinkToDeath(holder.mDeathMonitor, 0);
                    holder.mCallback.onSessionDestroyed();
            } catch (NoSuchElementException e) {
                logCallbackException("error unlinking to binder death", holder, e);
            } catch (DeadObjectException e) {
                logCallbackException("Removing dead callback in pushSessionDestroyed", holder, e);
            } catch (RemoteException e) {
                logCallbackException("unexpected exception in pushSessionDestroyed", holder, e);
                });
        // After notifying clear all listeners
        synchronized (mLock) {
            mControllerCallbackHolders.clear();
        }
    }
        // After notifying clear all listeners
        removeControllerHoldersSafely(null);

    private interface ControllerCallbackCall {

        void performOn(ISessionControllerCallbackHolder holder) throws RemoteException;
    }

    private void performOnCallbackHolders(String operationName, ControllerCallbackCall call) {
        ArrayList<ISessionControllerCallbackHolder> deadCallbackHolders = new ArrayList<>();
        for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
            try {
                call.performOn(holder);
            } catch (RemoteException | NoSuchElementException exception) {
                deadCallbackHolders.add(holder);
                logCallbackException(
                        "Exception while executing: " + operationName, holder, exception);
            }
        }
        synchronized (mLock) {
            mControllerCallbackHolders.removeAll(deadCallbackHolders);
        }
    }

    private PlaybackState getStateWithUpdatedPosition() {
@@ -1027,17 +941,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
        return -1;
    }

    private void removeControllerHoldersSafely(
            Collection<ISessionControllerCallbackHolder> holders) {
        synchronized (mLock) {
            if (holders == null) {
                mControllerCallbackHolders.clear();
            } else {
                mControllerCallbackHolders.removeAll(holders);
            }
        }
    }

    private PlaybackInfo getVolumeAttributes() {
        int volumeType;
        AudioAttributes attributes;