diff options
author | David Morrissey <davemorrissey@gmail.com> | 2017-11-24 12:46:45 +0000 |
---|---|---|
committer | David Morrissey <davemorrissey@gmail.com> | 2017-11-24 12:46:45 +0000 |
commit | 6bb6ea7b1723db9fec0642a1391c848a0e5882c6 (patch) | |
tree | b74fcda2034270a2d17511257eca381a13b2a714 | |
parent | e8c3772bd72581d06bab40be72f4bd5b2da82909 (diff) | |
download | subsampling-scale-image-view-6bb6ea7b1723db9fec0642a1391c848a0e5882c6.tar.gz |
Restored enforced synchronization on BitmapRegionDecoder for SDK < 21, which did not have internal synchronization
-rw-r--r-- | library/src/main/java/com/davemorrissey/labs/subscaleview/decoder/SkiaImageRegionDecoder.java | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/library/src/main/java/com/davemorrissey/labs/subscaleview/decoder/SkiaImageRegionDecoder.java b/library/src/main/java/com/davemorrissey/labs/subscaleview/decoder/SkiaImageRegionDecoder.java index 9d216f6..28f5d80 100644 --- a/library/src/main/java/com/davemorrissey/labs/subscaleview/decoder/SkiaImageRegionDecoder.java +++ b/library/src/main/java/com/davemorrissey/labs/subscaleview/decoder/SkiaImageRegionDecoder.java @@ -7,10 +7,12 @@ import android.content.res.AssetManager; import android.content.res.Resources; import android.graphics.*; import android.net.Uri; +import android.os.Build; import android.text.TextUtils; import java.io.InputStream; import java.util.List; +import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -21,9 +23,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * however it has some problems with grayscale, indexed and CMYK images. * * A {@link ReadWriteLock} is used to delegate responsibility for multi threading behaviour to the - * {@link BitmapRegionDecoder} instance, whilst allowing this class to block until no tiles are being - * loaded before recycling the decoder. In practice, {@link BitmapRegionDecoder} is single threaded - * so this has no real impact on performance. + * {@link BitmapRegionDecoder} instance on SDK >= 21, whilst allowing this class to block until no + * tiles are being loaded before recycling the decoder. In practice, {@link BitmapRegionDecoder} is + * synchronized internally so this has no real impact on performance. */ public class SkiaImageRegionDecoder implements ImageRegionDecoder { @@ -97,7 +99,7 @@ public class SkiaImageRegionDecoder implements ImageRegionDecoder { @Override public Bitmap decodeRegion(Rect sRect, int sampleSize) { - decoderLock.readLock().lock(); + getDecodeLock().lock(); try { if (decoder != null && !decoder.isRecycled()) { BitmapFactory.Options options = new BitmapFactory.Options(); @@ -112,27 +114,36 @@ public class SkiaImageRegionDecoder implements ImageRegionDecoder { throw new IllegalStateException("Cannot decode region after decoder has been recycled"); } } finally { - decoderLock.readLock().unlock(); + getDecodeLock().unlock(); } } @Override - public boolean isReady() { - decoderLock.readLock().lock(); - try { - return decoder != null && !decoder.isRecycled(); - } finally { - decoderLock.readLock().unlock(); - } + public synchronized boolean isReady() { + return decoder != null && !decoder.isRecycled(); } @Override - public void recycle() { + public synchronized void recycle() { decoderLock.writeLock().lock(); try { decoder.recycle(); + decoder = null; } finally { decoderLock.writeLock().unlock(); } } + + /** + * Before SDK 21, BitmapRegionDecoder was not synchronized internally. Any attempt to decode + * regions from multiple threads with one decoder instance causes a segfault. For old versions + * use the write lock to enforce single threaded decoding. + */ + private Lock getDecodeLock() { + if (Build.VERSION.SDK_INT < 21) { + return decoderLock.writeLock(); + } else { + return decoderLock.readLock(); + } + } } |