diff options
author | android-build-prod (mdb) <android-build-team-robot@google.com> | 2020-09-28 11:21:52 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-09-28 11:21:52 +0000 |
commit | 204ae28762ca34a43aadae9ae6f68ba65f745550 (patch) | |
tree | 45e8d3ee64dec39c325eeba8e5752570a3ccaf49 | |
parent | 0280c6c13e547fce5fc944363bb6b6dc4d685ab0 (diff) | |
parent | 821d73d97303e15ed94ad9ff970a92938b8988f7 (diff) | |
download | support-snap-temp-L68700000702621395.tar.gz |
Merge "Merge cherrypicks of [1440911] into androidx-exifinterface-release" into androidx-exifinterface-releasesnap-temp-L97900000702722496snap-temp-L68700000702621395snap-temp-L47400000702709972
-rw-r--r-- | exifinterface/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java | 103 |
1 files changed, 67 insertions, 36 deletions
diff --git a/exifinterface/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java b/exifinterface/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java index ec9ce09c0bf..28f3f931662 100644 --- a/exifinterface/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java +++ b/exifinterface/exifinterface/src/main/java/androidx/exifinterface/media/ExifInterface.java @@ -24,6 +24,7 @@ import android.location.Location; import android.media.MediaDataSource; import android.media.MediaMetadataRetriever; import android.os.Build; +import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.util.Log; @@ -32,6 +33,7 @@ import android.util.Pair; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; import androidx.annotation.RestrictTo; import java.io.BufferedInputStream; @@ -67,7 +69,6 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TimeZone; -import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -3946,12 +3947,8 @@ public class ExifInterface { // 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); - isFdDuped = true; - } catch (Exception e) { - throw new IOException("Failed to duplicate file descriptor", e); - } + fileDescriptor = OsApi21Impl.dup(fileDescriptor); + isFdDuped = true; } else { mSeekableFileDescriptor = null; } @@ -4607,7 +4604,7 @@ public class ExifInterface { private static boolean isSeekableFD(FileDescriptor fd) { if (Build.VERSION.SDK_INT >= 21) { try { - Os.lseek(fd, 0, OsConstants.SEEK_CUR); + OsApi21Impl.lseek(fd, 0, OsConstants.SEEK_CUR); return true; } catch (Exception e) { if (DEBUG) { @@ -4667,28 +4664,18 @@ public class ExifInterface { FileInputStream in = null; FileOutputStream out = null; - File originalFile = null; - if (mFilename != null) { - originalFile = new File(mFilename); - } File tempFile = null; try { - // Move the original file to temporary file. + // Copy the original file to temporary file. + tempFile = File.createTempFile("temp", "tmp"); if (mFilename != null) { - String parent = originalFile.getParent(); - String name = originalFile.getName(); - String tempPrefix = UUID.randomUUID().toString() + "_"; - tempFile = new File(parent, tempPrefix + name); - if (!originalFile.renameTo(tempFile)) { - throw new IOException("Couldn't rename to " + tempFile.getAbsolutePath()); - } + in = new FileInputStream(mFilename); } else if (Build.VERSION.SDK_INT >= 21 && mSeekableFileDescriptor != null) { - tempFile = File.createTempFile("temp", "tmp"); - Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET); + OsApi21Impl.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET); in = new FileInputStream(mSeekableFileDescriptor); - out = new FileOutputStream(tempFile); - copy(in, out); } + out = new FileOutputStream(tempFile); + copy(in, out); } catch (Exception e) { throw new IOException("Failed to copy original file to temp file", e); } finally { @@ -4706,7 +4693,7 @@ public class ExifInterface { if (mFilename != null) { out = new FileOutputStream(mFilename); } else if (Build.VERSION.SDK_INT >= 21 && mSeekableFileDescriptor != null) { - Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET); + OsApi21Impl.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET); out = new FileOutputStream(mSeekableFileDescriptor); } bufferedIn = new BufferedInputStream(in); @@ -4719,12 +4706,26 @@ public class ExifInterface { saveWebpAttributes(bufferedIn, bufferedOut); } } catch (Exception e) { + // Restore original file + closeQuietly(bufferedIn); + closeQuietly(bufferedOut); + in = new FileInputStream(tempFile); if (mFilename != null) { - if (!tempFile.renameTo(originalFile)) { - throw new IOException("Couldn't restore original file: " - + originalFile.getAbsolutePath()); + out = new FileOutputStream(mFilename); + } else if (Build.VERSION.SDK_INT >= 21 && mSeekableFileDescriptor != null) { + try { + OsApi21Impl.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET); + // Catching ErrnoException will raise error in API < 21 + } catch (Exception exception) { + throw new IOException("Failed to save new file. Original file may be " + + "corrupted since error occurred while trying to restore it.", + exception); } + out = new FileOutputStream(mSeekableFileDescriptor); } + copy(in, out); + closeQuietly(in); + closeQuietly(out); throw new IOException("Failed to save new file", e); } finally { closeQuietly(bufferedIn); @@ -4794,8 +4795,8 @@ public class ExifInterface { } else if (mFilename != null) { in = new FileInputStream(mFilename); } else if (Build.VERSION.SDK_INT >= 21 && mSeekableFileDescriptor != null) { - newFileDescriptor = Os.dup(mSeekableFileDescriptor); - Os.lseek(newFileDescriptor, 0, OsConstants.SEEK_SET); + newFileDescriptor = OsApi21Impl.dup(mSeekableFileDescriptor); + OsApi21Impl.lseek(newFileDescriptor, 0, OsConstants.SEEK_SET); in = new FileInputStream(newFileDescriptor); } if (in == null) { @@ -7985,12 +7986,7 @@ public class ExifInterface { // Os.dup and Os.close was introduced in API 21 so this method shouldn't be called // in API < 21. if (Build.VERSION.SDK_INT >= 21) { - try { - Os.close(fd); - // Catching ErrnoException will raise error in API < 21 - } catch (Exception ex) { - Log.e(TAG, "Error closing fd."); - } + OsApi21Impl.close(fd); } else { Log.e(TAG, "closeFileDescriptor is called in API < 21, which must be wrong."); } @@ -8078,4 +8074,39 @@ public class ExifInterface { } return false; } + + /** + * Nested class to avoid verification errors for methods introduced in Android 5.0 (API 21). + */ + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) + private static class OsApi21Impl { + // Prevent instantiation. + private OsApi21Impl() {} + + static FileDescriptor dup(FileDescriptor fd) throws IOException { + FileDescriptor duplicateFD = null; + try { + duplicateFD = Os.dup(fd); + } catch (ErrnoException e) { + throw new IOException("Failed to duplicate file descriptor", e); + } + return duplicateFD; + } + + static void close(FileDescriptor fd) { + try { + Os.close(fd); + } catch (ErrnoException ex) { + Log.e(TAG, "Error closing fd."); + } + } + + static void lseek(FileDescriptor fd, int offset, int osConstant) throws IOException { + try { + Os.lseek(fd, offset, osConstant); + } catch (ErrnoException e) { + throw new IOException("Failed to seek file descriptor", e); + } + } + } } |