From 2290a6c0df275198e7749b7d6e3fd3e0511ef8db Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Tue, 17 Nov 2020 14:42:01 -0400 Subject: [PATCH] Synchronize voice note queue reads and writes. --- .../voice/VoiceNotePlaybackPreparer.java | 80 ++++++++++--------- .../voice/VoiceNoteQueueDataAdapter.java | 18 ++--- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/voice/VoiceNotePlaybackPreparer.java b/app/src/main/java/org/thoughtcrime/securesms/components/voice/VoiceNotePlaybackPreparer.java index 968432dc4..95646ef68 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/voice/VoiceNotePlaybackPreparer.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/voice/VoiceNotePlaybackPreparer.java @@ -140,56 +140,58 @@ final class VoiceNotePlaybackPreparer implements MediaSessionConnector.PlaybackP } private void applyDescriptionsToQueue(@NonNull List descriptions) { - for (MediaDescriptionCompat description : descriptions) { - int holderIndex = queueDataAdapter.indexOf(description.getMediaUri()); - MediaDescriptionCompat next = createNextClone(description); - int currentIndex = player.getCurrentWindowIndex(); + synchronized (queueDataAdapter) { + for (MediaDescriptionCompat description : descriptions) { + int holderIndex = queueDataAdapter.indexOf(description.getMediaUri()); + MediaDescriptionCompat next = createNextClone(description); + int currentIndex = player.getCurrentWindowIndex(); - if (holderIndex != -1) { - queueDataAdapter.remove(holderIndex); - - if (!queueDataAdapter.isEmpty()) { + if (holderIndex != -1) { queueDataAdapter.remove(holderIndex); - } - queueDataAdapter.add(holderIndex, createNextClone(description)); - queueDataAdapter.add(holderIndex, description); - - if (currentIndex != holderIndex) { - dataSource.removeMediaSource(holderIndex); - dataSource.addMediaSource(holderIndex, mediaSourceFactory.createMediaSource(description)); - } - - if (currentIndex != holderIndex + 1) { - if (dataSource.getSize() > 1) { - dataSource.removeMediaSource(holderIndex + 1); + if (!queueDataAdapter.isEmpty()) { + queueDataAdapter.remove(holderIndex); } - dataSource.addMediaSource(holderIndex + 1, mediaSourceFactory.createMediaSource(next)); + queueDataAdapter.add(holderIndex, createNextClone(description)); + queueDataAdapter.add(holderIndex, description); + + if (currentIndex != holderIndex) { + dataSource.removeMediaSource(holderIndex); + dataSource.addMediaSource(holderIndex, mediaSourceFactory.createMediaSource(description)); + } + + if (currentIndex != holderIndex + 1) { + if (dataSource.getSize() > 1) { + dataSource.removeMediaSource(holderIndex + 1); + } + + dataSource.addMediaSource(holderIndex + 1, mediaSourceFactory.createMediaSource(next)); + } + } else { + int insertLocation = queueDataAdapter.indexAfter(description); + + queueDataAdapter.add(insertLocation, next); + queueDataAdapter.add(insertLocation, description); + + dataSource.addMediaSource(insertLocation, mediaSourceFactory.createMediaSource(next)); + dataSource.addMediaSource(insertLocation, mediaSourceFactory.createMediaSource(description)); } - } else { - int insertLocation = queueDataAdapter.indexAfter(description); - - queueDataAdapter.add(insertLocation, next); - queueDataAdapter.add(insertLocation, description); - - dataSource.addMediaSource(insertLocation, mediaSourceFactory.createMediaSource(next)); - dataSource.addMediaSource(insertLocation, mediaSourceFactory.createMediaSource(description)); } - } - int lastIndex = queueDataAdapter.size() - 1; - MediaDescriptionCompat last = queueDataAdapter.getMediaDescription(lastIndex); + int lastIndex = queueDataAdapter.size() - 1; + MediaDescriptionCompat last = queueDataAdapter.getMediaDescription(lastIndex); - if (Objects.equals(last.getMediaUri(), NEXT_URI)) { - queueDataAdapter.remove(lastIndex); - dataSource.removeMediaSource(lastIndex); + if (Objects.equals(last.getMediaUri(), NEXT_URI)) { + queueDataAdapter.remove(lastIndex); + dataSource.removeMediaSource(lastIndex); - if (queueDataAdapter.size() > 1) { - MediaDescriptionCompat end = createEndClone(last); + if (queueDataAdapter.size() > 1) { + MediaDescriptionCompat end = createEndClone(last); - queueDataAdapter.add(lastIndex, end); - dataSource.addMediaSource(lastIndex, mediaSourceFactory.createMediaSource(end)); + queueDataAdapter.add(lastIndex, end); + dataSource.addMediaSource(lastIndex, mediaSourceFactory.createMediaSource(end)); + } } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/voice/VoiceNoteQueueDataAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/components/voice/VoiceNoteQueueDataAdapter.java index 85f965a56..97210216e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/voice/VoiceNoteQueueDataAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/voice/VoiceNoteQueueDataAdapter.java @@ -20,31 +20,31 @@ final class VoiceNoteQueueDataAdapter implements TimelineQueueEditor.QueueDataAd private final List descriptions = new LinkedList<>(); @Override - public MediaDescriptionCompat getMediaDescription(int position) { + public synchronized MediaDescriptionCompat getMediaDescription(int position) { return descriptions.get(position); } @Override - public void add(int position, MediaDescriptionCompat description) { + public synchronized void add(int position, MediaDescriptionCompat description) { descriptions.add(position, description); } @Override - public void remove(int position) { + public synchronized void remove(int position) { descriptions.remove(position); } @Override - public void move(int from, int to) { + public synchronized void move(int from, int to) { MediaDescriptionCompat description = descriptions.remove(from); descriptions.add(to, description); } - int size() { + synchronized int size() { return descriptions.size(); } - int indexOf(@NonNull Uri uri) { + synchronized int indexOf(@NonNull Uri uri) { for (int i = 0; i < descriptions.size(); i++) { if (Objects.equals(uri, descriptions.get(i).getMediaUri())) { return i; @@ -54,7 +54,7 @@ final class VoiceNoteQueueDataAdapter implements TimelineQueueEditor.QueueDataAd return -1; } - int indexAfter(@NonNull MediaDescriptionCompat target) { + synchronized int indexAfter(@NonNull MediaDescriptionCompat target) { if (isEmpty()) { return 0; } @@ -71,11 +71,11 @@ final class VoiceNoteQueueDataAdapter implements TimelineQueueEditor.QueueDataAd return descriptions.size(); } - boolean isEmpty() { + synchronized boolean isEmpty() { return descriptions.isEmpty(); } - void clear() { + synchronized void clear() { descriptions.clear(); } }