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

Commit e5e456e9 authored by Weilin Xu's avatar Weilin Xu Committed by Automerger Merge Worker
Browse files

Merge "Fix deadlock due to callbacks in ProgramList" into tm-qpr-dev am: 5355bffe

parents b5877362 5355bffe
Loading
Loading
Loading
Loading
+34 −10
Original line number Original line Diff line number Diff line
@@ -26,7 +26,6 @@ import android.os.Parcelable;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Objects;
import java.util.Objects;
@@ -173,38 +172,63 @@ public final class ProgramList implements AutoCloseable {
        }
        }
    }
    }


    void apply(@NonNull Chunk chunk) {
    void apply(Chunk chunk) {
        List<ProgramSelector.Identifier> removedList = new ArrayList<>();
        List<ProgramSelector.Identifier> changedList = new ArrayList<>();
        List<ProgramList.ListCallback> listCallbacksCopied;
        List<OnCompleteListener> onCompleteListenersCopied = new ArrayList<>();
        synchronized (mLock) {
        synchronized (mLock) {
            if (mIsClosed) return;
            if (mIsClosed) return;


            mIsComplete = false;
            mIsComplete = false;
            listCallbacksCopied = new ArrayList<>(mListCallbacks);


            if (chunk.isPurge()) {
            if (chunk.isPurge()) {
                new HashSet<>(mPrograms.keySet()).stream().forEach(id -> removeLocked(id));
                for (ProgramSelector.Identifier id : mPrograms.keySet()) {
                    removeLocked(id, removedList);
                }
            }
            }


            chunk.getRemoved().stream().forEach(id -> removeLocked(id));
            chunk.getRemoved().stream().forEach(id -> removeLocked(id, removedList));
            chunk.getModified().stream().forEach(info -> putLocked(info));
            chunk.getModified().stream().forEach(info -> putLocked(info, changedList));


            if (chunk.isComplete()) {
            if (chunk.isComplete()) {
                mIsComplete = true;
                mIsComplete = true;
                mOnCompleteListeners.forEach(cb -> cb.onComplete());
                onCompleteListenersCopied = new ArrayList<>(mOnCompleteListeners);
            }
        }

        for (int i = 0; i < removedList.size(); i++) {
            for (int cbIndex = 0; cbIndex < listCallbacksCopied.size(); cbIndex++) {
                listCallbacksCopied.get(cbIndex).onItemRemoved(removedList.get(i));
            }
        }
        for (int i = 0; i < changedList.size(); i++) {
            for (int cbIndex = 0; cbIndex < listCallbacksCopied.size(); cbIndex++) {
                listCallbacksCopied.get(cbIndex).onItemChanged(changedList.get(i));
            }
        }
        if (chunk.isComplete()) {
            for (int cbIndex = 0; cbIndex < onCompleteListenersCopied.size(); cbIndex++) {
                onCompleteListenersCopied.get(cbIndex).onComplete();
            }
            }
        }
        }
    }
    }


    private void putLocked(@NonNull RadioManager.ProgramInfo value) {
    private void putLocked(RadioManager.ProgramInfo value,
            List<ProgramSelector.Identifier> changedIdentifierList) {
        ProgramSelector.Identifier key = value.getSelector().getPrimaryId();
        ProgramSelector.Identifier key = value.getSelector().getPrimaryId();
        mPrograms.put(Objects.requireNonNull(key), value);
        mPrograms.put(Objects.requireNonNull(key), value);
        ProgramSelector.Identifier sel = value.getSelector().getPrimaryId();
        ProgramSelector.Identifier sel = value.getSelector().getPrimaryId();
        mListCallbacks.forEach(cb -> cb.onItemChanged(sel));
        changedIdentifierList.add(sel);
    }
    }


    private void removeLocked(@NonNull ProgramSelector.Identifier key) {
    private void removeLocked(ProgramSelector.Identifier key,
            List<ProgramSelector.Identifier> removedIdentifierList) {
        RadioManager.ProgramInfo removed = mPrograms.remove(Objects.requireNonNull(key));
        RadioManager.ProgramInfo removed = mPrograms.remove(Objects.requireNonNull(key));
        if (removed == null) return;
        if (removed == null) return;
        ProgramSelector.Identifier sel = removed.getSelector().getPrimaryId();
        ProgramSelector.Identifier sel = removed.getSelector().getPrimaryId();
        mListCallbacks.forEach(cb -> cb.onItemRemoved(sel));
        removedIdentifierList.add(sel);
    }
    }


    /**
    /**