aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-prod (mdb) <android-build-team-robot@google.com>2020-09-28 11:21:52 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2020-09-28 11:21:52 +0000
commit204ae28762ca34a43aadae9ae6f68ba65f745550 (patch)
tree45e8d3ee64dec39c325eeba8e5752570a3ccaf49
parent0280c6c13e547fce5fc944363bb6b6dc4d685ab0 (diff)
parent821d73d97303e15ed94ad9ff970a92938b8988f7 (diff)
downloadsupport-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.java103
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);
+ }
+ }
+ }
}