Ensure that the decoder is thread-safe.

This prevents issues where one thread recycles the decoder while another
thread is in the process of checking the decoder's status or in the process
of decoding a region.

bug: 6880937
Change-Id: I7f755bf2149d03594e528ca79c536713b1447a55
This commit is contained in:
Derek Sollenberger
2012-09-21 08:19:05 -04:00
parent 7b6ec1f6fd
commit cd77583ed3

View File

@@ -36,6 +36,9 @@ import java.io.InputStream;
public final class BitmapRegionDecoder {
private int mNativeBitmapRegionDecoder;
private boolean mRecycled;
// ensures that the native decoder object exists and that only one decode can
// occur at a time.
private final Object mNativeLock = new Object();
/**
* Create a BitmapRegionDecoder from the specified byte array.
@@ -179,24 +182,30 @@ public final class BitmapRegionDecoder {
* decoded.
*/
public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) {
checkRecycled("decodeRegion called on recycled region decoder");
if (rect.right <= 0 || rect.bottom <= 0 || rect.left >= getWidth()
|| rect.top >= getHeight())
throw new IllegalArgumentException("rectangle is outside the image");
return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, options);
synchronized (mNativeLock) {
checkRecycled("decodeRegion called on recycled region decoder");
if (rect.right <= 0 || rect.bottom <= 0 || rect.left >= getWidth()
|| rect.top >= getHeight())
throw new IllegalArgumentException("rectangle is outside the image");
return nativeDecodeRegion(mNativeBitmapRegionDecoder, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, options);
}
}
/** Returns the original image's width */
public int getWidth() {
checkRecycled("getWidth called on recycled region decoder");
return nativeGetWidth(mNativeBitmapRegionDecoder);
synchronized (mNativeLock) {
checkRecycled("getWidth called on recycled region decoder");
return nativeGetWidth(mNativeBitmapRegionDecoder);
}
}
/** Returns the original image's height */
public int getHeight() {
checkRecycled("getHeight called on recycled region decoder");
return nativeGetHeight(mNativeBitmapRegionDecoder);
synchronized (mNativeLock) {
checkRecycled("getHeight called on recycled region decoder");
return nativeGetHeight(mNativeBitmapRegionDecoder);
}
}
/**
@@ -210,9 +219,11 @@ public final class BitmapRegionDecoder {
* memory when there are no more references to this region decoder.
*/
public void recycle() {
if (!mRecycled) {
nativeClean(mNativeBitmapRegionDecoder);
mRecycled = true;
synchronized (mNativeLock) {
if (!mRecycled) {
nativeClean(mNativeBitmapRegionDecoder);
mRecycled = true;
}
}
}