Merge "ExifInterface: close the resource after reading EXIF data explicitly" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
976bbaccc4
@@ -651,6 +651,7 @@ public class ExifInterface {
|
||||
private final String mFilename;
|
||||
private final FileDescriptor mSeekableFileDescriptor;
|
||||
private final AssetManager.AssetInputStream mAssetInputStream;
|
||||
private final boolean mIsInputStream;
|
||||
private boolean mIsRaw;
|
||||
private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
|
||||
private boolean mHasThumbnail;
|
||||
@@ -669,20 +670,26 @@ public class ExifInterface {
|
||||
if (filename == null) {
|
||||
throw new IllegalArgumentException("filename cannot be null");
|
||||
}
|
||||
FileInputStream in = new FileInputStream(filename);
|
||||
FileInputStream in = null;
|
||||
mAssetInputStream = null;
|
||||
mFilename = filename;
|
||||
if (isSeekableFD(in.getFD())) {
|
||||
mSeekableFileDescriptor = in.getFD();
|
||||
} else {
|
||||
mSeekableFileDescriptor = null;
|
||||
mIsInputStream = false;
|
||||
try {
|
||||
in = new FileInputStream(filename);
|
||||
if (isSeekableFD(in.getFD())) {
|
||||
mSeekableFileDescriptor = in.getFD();
|
||||
} else {
|
||||
mSeekableFileDescriptor = null;
|
||||
}
|
||||
loadAttributes(in);
|
||||
} finally {
|
||||
IoUtils.closeQuietly(in);
|
||||
}
|
||||
loadAttributes(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads Exif tags from the specified image file descriptor. Attribute mutation is supported
|
||||
* for seekable file descriptors only.
|
||||
* for writable and seekable file descriptors only.
|
||||
*/
|
||||
public ExifInterface(FileDescriptor fileDescriptor) throws IOException {
|
||||
if (fileDescriptor == null) {
|
||||
@@ -692,10 +699,25 @@ public class ExifInterface {
|
||||
mFilename = null;
|
||||
if (isSeekableFD(fileDescriptor)) {
|
||||
mSeekableFileDescriptor = fileDescriptor;
|
||||
// Keep the original file descriptor in order to save attributes when it's seekable.
|
||||
// Otherwise, just close the given file descriptor after reading it because the save
|
||||
// feature won't be working.
|
||||
try {
|
||||
fileDescriptor = Os.dup(fileDescriptor);
|
||||
} catch (ErrnoException e) {
|
||||
e.rethrowAsIOException();
|
||||
}
|
||||
} else {
|
||||
mSeekableFileDescriptor = null;
|
||||
}
|
||||
loadAttributes(new FileInputStream(fileDescriptor));
|
||||
mIsInputStream = false;
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(fileDescriptor);
|
||||
loadAttributes(in);
|
||||
} finally {
|
||||
IoUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -718,6 +740,7 @@ public class ExifInterface {
|
||||
mAssetInputStream = null;
|
||||
mSeekableFileDescriptor = null;
|
||||
}
|
||||
mIsInputStream = true;
|
||||
loadAttributes(inputStream);
|
||||
}
|
||||
|
||||
@@ -800,32 +823,32 @@ public class ExifInterface {
|
||||
* determine whether the image data format is JPEG or not.
|
||||
*/
|
||||
private void loadAttributes(@NonNull InputStream in) throws IOException {
|
||||
// Initialize mAttributes.
|
||||
for (int i = 0; i < EXIF_TAGS.length; ++i) {
|
||||
mAttributes[i] = new HashMap();
|
||||
}
|
||||
|
||||
// Process RAW input stream
|
||||
if (mAssetInputStream != null) {
|
||||
long asset = mAssetInputStream.getNativeAsset();
|
||||
if (handleRawResult(nativeGetRawAttributesFromAsset(asset))) {
|
||||
return;
|
||||
}
|
||||
} else if (mSeekableFileDescriptor != null) {
|
||||
if (handleRawResult(nativeGetRawAttributesFromFileDescriptor(
|
||||
mSeekableFileDescriptor))) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
in = new BufferedInputStream(in, JPEG_SIGNATURE_SIZE);
|
||||
if (!isJpegInputStream((BufferedInputStream) in) && handleRawResult(
|
||||
nativeGetRawAttributesFromInputStream(in))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Process JPEG input stream
|
||||
try {
|
||||
// Initialize mAttributes.
|
||||
for (int i = 0; i < EXIF_TAGS.length; ++i) {
|
||||
mAttributes[i] = new HashMap();
|
||||
}
|
||||
|
||||
// Process RAW input stream
|
||||
if (mAssetInputStream != null) {
|
||||
long asset = mAssetInputStream.getNativeAsset();
|
||||
if (handleRawResult(nativeGetRawAttributesFromAsset(asset))) {
|
||||
return;
|
||||
}
|
||||
} else if (mSeekableFileDescriptor != null) {
|
||||
if (handleRawResult(nativeGetRawAttributesFromFileDescriptor(
|
||||
mSeekableFileDescriptor))) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
in = new BufferedInputStream(in, JPEG_SIGNATURE_SIZE);
|
||||
if (!isJpegInputStream((BufferedInputStream) in) && handleRawResult(
|
||||
nativeGetRawAttributesFromInputStream(in))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Process JPEG input stream
|
||||
getJpegAttributes(in);
|
||||
} catch (IOException e) {
|
||||
// Ignore exceptions in order to keep the compatibility with the old versions of
|
||||
@@ -833,10 +856,10 @@ public class ExifInterface {
|
||||
Log.w(TAG, "Invalid JPEG: ExifInterface got an unsupported image format file"
|
||||
+ "(ExifInterface supports JPEG and some RAW image formats only) "
|
||||
+ "or a corrupted JPEG file to ExifInterface.", e);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
printAttributes();
|
||||
} finally {
|
||||
if (DEBUG) {
|
||||
printAttributes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -880,10 +903,6 @@ public class ExifInterface {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
printAttributes();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -917,7 +936,7 @@ public class ExifInterface {
|
||||
throw new UnsupportedOperationException(
|
||||
"ExifInterface does not support saving attributes on RAW formats.");
|
||||
}
|
||||
if (mSeekableFileDescriptor == null && mFilename == null) {
|
||||
if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) {
|
||||
throw new UnsupportedOperationException(
|
||||
"ExifInterface does not support saving attributes for the current input.");
|
||||
}
|
||||
@@ -1003,8 +1022,9 @@ public class ExifInterface {
|
||||
} else if (mFilename != null) {
|
||||
in = new FileInputStream(mFilename);
|
||||
} else if (mSeekableFileDescriptor != null) {
|
||||
Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET);
|
||||
in = new FileInputStream(mSeekableFileDescriptor);
|
||||
FileDescriptor fileDescriptor = Os.dup(mSeekableFileDescriptor);
|
||||
Os.lseek(fileDescriptor, 0, OsConstants.SEEK_SET);
|
||||
in = new FileInputStream(fileDescriptor);
|
||||
}
|
||||
if (in == null) {
|
||||
// Should not be reached this.
|
||||
|
||||
Reference in New Issue
Block a user