Merge "Fix deadlock due to callbacks in ProgramList" into tm-qpr-dev am: 5355bffe3a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19120223 Change-Id: I6635f3da3bdaddf105dba7329314920472990709 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user