diff options
| -rw-r--r-- | media/java/android/media/ExifInterface.java | 94 | ||||
| -rw-r--r-- | media/java/android/media/ExifInterfaceUtils.java | 117 |
2 files changed, 135 insertions, 76 deletions
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index ed566a50ec58..6d690f0aa397 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -16,6 +16,12 @@ package android.media; +import static android.media.ExifInterfaceUtils.byteArrayToHexString; +import static android.media.ExifInterfaceUtils.closeQuietly; +import static android.media.ExifInterfaceUtils.convertToLongArray; +import static android.media.ExifInterfaceUtils.copy; +import static android.media.ExifInterfaceUtils.startsWith; + import android.annotation.CurrentTimeMillisLong; import android.annotation.IntDef; import android.annotation.NonNull; @@ -32,10 +38,6 @@ import android.util.Log; import android.util.Pair; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.ArrayUtils; - -import libcore.io.IoUtils; -import libcore.io.Streams; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -1540,7 +1542,7 @@ public class ExifInterface { in = new FileInputStream(fileDescriptor, isFdOwner); loadAttributes(in); } finally { - IoUtils.closeQuietly(in); + closeQuietly(in); } } @@ -2092,13 +2094,13 @@ public class ExifInterface { Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET); in = new FileInputStream(mSeekableFileDescriptor); out = new FileOutputStream(tempFile); - Streams.copy(in, out); + copy(in, out); } } catch (Exception e) { throw new IOException("Failed to copy original file to temp file", e); } finally { - IoUtils.closeQuietly(in); - IoUtils.closeQuietly(out); + closeQuietly(in); + closeQuietly(out); } in = null; @@ -2129,8 +2131,8 @@ public class ExifInterface { } throw new IOException("Failed to save new file", e); } finally { - IoUtils.closeQuietly(in); - IoUtils.closeQuietly(out); + closeQuietly(in); + closeQuietly(out); tempFile.delete(); } @@ -2215,7 +2217,7 @@ public class ExifInterface { // Couldn't get a thumbnail image. Log.d(TAG, "Encountered exception while getting thumbnail", e); } finally { - IoUtils.closeQuietly(in); + closeQuietly(in); } return null; } @@ -2536,7 +2538,7 @@ public class ExifInterface { } loadAttributes(in); } finally { - IoUtils.closeQuietly(in); + closeQuietly(in); } } @@ -2839,14 +2841,14 @@ public class ExifInterface { bytesRead += length; length = 0; - if (ArrayUtils.startsWith(bytes, IDENTIFIER_EXIF_APP1)) { + if (startsWith(bytes, IDENTIFIER_EXIF_APP1)) { final long offset = start + IDENTIFIER_EXIF_APP1.length; final byte[] value = Arrays.copyOfRange(bytes, IDENTIFIER_EXIF_APP1.length, bytes.length); // Save offset values for handleThumbnailFromJfif() function mExifOffset = (int) offset; readExifSegment(value, imageType); - } else if (ArrayUtils.startsWith(bytes, IDENTIFIER_XMP_APP1)) { + } else if (startsWith(bytes, IDENTIFIER_XMP_APP1)) { // See XMP Specification Part 3: Storage in Files, 1.1.3 JPEG, Table 6 final long offset = start + IDENTIFIER_XMP_APP1.length; final byte[] value = Arrays.copyOfRange(bytes, @@ -3527,7 +3529,7 @@ public class ExifInterface { dataOutputStream.writeByte(MARKER); dataOutputStream.writeByte(marker); // Copy all the remaining data - Streams.copy(dataInputStream, dataOutputStream); + copy(dataInputStream, dataOutputStream); return; } default: { @@ -3605,7 +3607,7 @@ public class ExifInterface { dataOutputStream.writeInt((int) crc.getValue()); } // Copy the rest of the file - Streams.copy(dataInputStream, dataOutputStream); + copy(dataInputStream, dataOutputStream); } // Reads the given EXIF byte area and save its tag data into attributes. @@ -4865,64 +4867,4 @@ public class ExifInterface { } } } - - // Checks if there is a match - private boolean containsMatch(byte[] mainBytes, byte[] findBytes) { - for (int i = 0; i < mainBytes.length - findBytes.length; i++) { - for (int j = 0; j < findBytes.length; j++) { - if (mainBytes[i + j] != findBytes[j]) { - break; - } - if (j == findBytes.length - 1) { - return true; - } - } - } - return false; - } - - /** - * Copies the given number of the bytes from {@code in} to {@code out}. Neither stream is - * closed. - */ - private static void copy(InputStream in, OutputStream out, int numBytes) throws IOException { - int remainder = numBytes; - byte[] buffer = new byte[8192]; - while (remainder > 0) { - int bytesToRead = Math.min(remainder, 8192); - int bytesRead = in.read(buffer, 0, bytesToRead); - if (bytesRead != bytesToRead) { - throw new IOException("Failed to copy the given amount of bytes from the input" - + "stream to the output stream."); - } - remainder -= bytesRead; - out.write(buffer, 0, bytesRead); - } - } - - /** - * Convert given int[] to long[]. If long[] is given, just return it. - * Return null for other types of input. - */ - private static long[] convertToLongArray(Object inputObj) { - if (inputObj instanceof int[]) { - int[] input = (int[]) inputObj; - long[] result = new long[input.length]; - for (int i = 0; i < input.length; i++) { - result[i] = input[i]; - } - return result; - } else if (inputObj instanceof long[]) { - return (long[]) inputObj; - } - return null; - } - - private static String byteArrayToHexString(byte[] bytes) { - StringBuilder sb = new StringBuilder(bytes.length * 2); - for (int i = 0; i < bytes.length; i++) { - sb.append(String.format("%02x", bytes[i])); - } - return sb.toString(); - } } diff --git a/media/java/android/media/ExifInterfaceUtils.java b/media/java/android/media/ExifInterfaceUtils.java new file mode 100644 index 000000000000..6ff706e8041f --- /dev/null +++ b/media/java/android/media/ExifInterfaceUtils.java @@ -0,0 +1,117 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Package private utility class for ExifInterface. + */ +class ExifInterfaceUtils { + /** + * Copies all of the bytes from {@code in} to {@code out}. Neither stream is closed. + * Returns the total number of bytes transferred. + */ + public static int copy(InputStream in, OutputStream out) throws IOException { + int total = 0; + byte[] buffer = new byte[8192]; + int c; + while ((c = in.read(buffer)) != -1) { + total += c; + out.write(buffer, 0, c); + } + return total; + } + + /** + * Copies the given number of the bytes from {@code in} to {@code out}. Neither stream is + * closed. + */ + public static void copy(InputStream in, OutputStream out, int numBytes) throws IOException { + int remainder = numBytes; + byte[] buffer = new byte[8192]; + while (remainder > 0) { + int bytesToRead = Math.min(remainder, 8192); + int bytesRead = in.read(buffer, 0, bytesToRead); + if (bytesRead != bytesToRead) { + throw new IOException("Failed to copy the given amount of bytes from the input" + + "stream to the output stream."); + } + remainder -= bytesRead; + out.write(buffer, 0, bytesRead); + } + } + + /** + * Convert given int[] to long[]. If long[] is given, just return it. + * Return null for other types of input. + */ + public static long[] convertToLongArray(Object inputObj) { + if (inputObj instanceof int[]) { + int[] input = (int[]) inputObj; + long[] result = new long[input.length]; + for (int i = 0; i < input.length; i++) { + result[i] = input[i]; + } + return result; + } else if (inputObj instanceof long[]) { + return (long[]) inputObj; + } + return null; + } + + /** + * Convert given byte array to hex string. + */ + public static String byteArrayToHexString(byte[] bytes) { + StringBuilder sb = new StringBuilder(bytes.length * 2); + for (int i = 0; i < bytes.length; i++) { + sb.append(String.format("%02x", bytes[i])); + } + return sb.toString(); + } + + /** + * Checks if the start of the first byte array is equal to the second byte array. + */ + public static boolean startsWith(byte[] cur, byte[] val) { + if (cur == null || val == null) return false; + if (cur.length < val.length) return false; + if (cur.length == 0 || val.length == 0) return false; + for (int i = 0; i < val.length; i++) { + if (cur[i] != val[i]) return false; + } + return true; + } + + /** + * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null. + */ + public static void closeQuietly(Closeable closeable) { + if (closeable != null) { + try { + closeable.close(); + } catch (RuntimeException rethrown) { + throw rethrown; + } catch (Exception ignored) { + } + } + } +} |