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

Commit 8aea09fe authored by Soonil Nagarkar's avatar Soonil Nagarkar
Browse files

DO NOT MERGE Don't lock listener delivery

Previous versions of GNSS listeners commited to not holding locks even
when running directly unfortunately. We do some extra work to avoid
holding locks while running listeners.

Bug: 151291181
Test: manual
Change-Id: I0b7f46c30df2f97ce11db45b69443a9994885309
parent 2490ec4d
Loading
Loading
Loading
Loading
+23 −13
Original line number Diff line number Diff line
@@ -85,11 +85,13 @@ abstract class AbstractListenerManager<TRequest, TListener> {
        }
    }

    @GuardedBy("mListeners")
    private final ArrayMap<Object, Registration<TRequest, TListener>> mListeners =
    private final Object mLock = new Object();

    @GuardedBy("mLock")
    private volatile ArrayMap<Object, Registration<TRequest, TListener>> mListeners =
            new ArrayMap<>();

    @GuardedBy("mListeners")
    @GuardedBy("mLock")
    @Nullable
    private TRequest mMergedRequest;

@@ -129,10 +131,16 @@ abstract class AbstractListenerManager<TRequest, TListener> {
            throws RemoteException {
        Preconditions.checkNotNull(registration);

        synchronized (mListeners) {
        synchronized (mLock) {
            boolean initialRequest = mListeners.isEmpty();

            Registration<TRequest, TListener> oldRegistration = mListeners.put(key, registration);
            ArrayMap<Object, Registration<TRequest, TListener>> newListeners = new ArrayMap<>(
                    mListeners.size() + 1);
            newListeners.putAll(mListeners);
            Registration<TRequest, TListener> oldRegistration = newListeners.put(key,
                    registration);
            mListeners = newListeners;

            if (oldRegistration != null) {
                oldRegistration.unregister();
            }
@@ -151,8 +159,12 @@ abstract class AbstractListenerManager<TRequest, TListener> {
    }

    public void removeListener(Object listener) throws RemoteException {
        synchronized (mListeners) {
            Registration<TRequest, TListener> oldRegistration = mListeners.remove(listener);
        synchronized (mLock) {
            ArrayMap<Object, Registration<TRequest, TListener>> newListeners = new ArrayMap<>(
                    mListeners);
            Registration<TRequest, TListener> oldRegistration = newListeners.remove(listener);
            mListeners = newListeners;

            if (oldRegistration == null) {
                return;
            }
@@ -190,18 +202,16 @@ abstract class AbstractListenerManager<TRequest, TListener> {
    }

    protected void execute(Consumer<TListener> operation) {
        synchronized (mListeners) {
        for (Registration<TRequest, TListener> registration : mListeners.values()) {
            registration.execute(operation);
        }
    }
    }

    @GuardedBy("mListeners")
    @GuardedBy("mLock")
    @SuppressWarnings("unchecked")
    @Nullable
    private TRequest mergeRequests() {
        Preconditions.checkState(Thread.holdsLock(mListeners));
        Preconditions.checkState(Thread.holdsLock(mLock));

        if (mListeners.isEmpty()) {
            return null;