Parse Exif OffsetTime in MediaScanner
MediaScanner parses Exif OffsetTime value to use UTC time
for DATE_TAKEN value.
Bug: 62856173
Change-Id: Iffb7e0ae296b73ce6fb6515246871f0dcfe42bb0
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 23db27d..31a6b81 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -233,6 +233,12 @@
public static final String TAG_NEW_SUBFILE_TYPE = "NewSubfileType";
/** Type is String. */
public static final String TAG_OECF = "OECF";
+ /** Type is String. {@hide} */
+ public static final String TAG_OFFSET_TIME = "OffsetTime";
+ /** Type is String. {@hide} */
+ public static final String TAG_OFFSET_TIME_ORIGINAL = "OffsetTimeOriginal";
+ /** Type is String. {@hide} */
+ public static final String TAG_OFFSET_TIME_DIGITIZED = "OffsetTimeDigitized";
/** Type is int. */
public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
/** Type is int. */
@@ -486,6 +492,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private static SimpleDateFormat sFormatter;
+ private static SimpleDateFormat sFormatterTz;
// See Exchangeable image file format for digital still cameras: Exif version 2.2.
// The following values are for parsing EXIF data area. There are tag groups in EXIF data area.
@@ -1041,6 +1048,9 @@
new ExifTag(TAG_EXIF_VERSION, 36864, IFD_FORMAT_STRING),
new ExifTag(TAG_DATETIME_ORIGINAL, 36867, IFD_FORMAT_STRING),
new ExifTag(TAG_DATETIME_DIGITIZED, 36868, IFD_FORMAT_STRING),
+ new ExifTag(TAG_OFFSET_TIME, 36880, IFD_FORMAT_STRING),
+ new ExifTag(TAG_OFFSET_TIME_ORIGINAL, 36881, IFD_FORMAT_STRING),
+ new ExifTag(TAG_OFFSET_TIME_DIGITIZED, 36882, IFD_FORMAT_STRING),
new ExifTag(TAG_COMPONENTS_CONFIGURATION, 37121, IFD_FORMAT_UNDEFINED),
new ExifTag(TAG_COMPRESSED_BITS_PER_PIXEL, 37122, IFD_FORMAT_URATIONAL),
new ExifTag(TAG_SHUTTER_SPEED_VALUE, 37377, IFD_FORMAT_SRATIONAL),
@@ -1301,6 +1311,8 @@
static {
sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+ sFormatterTz = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss XXX");
+ sFormatterTz.setTimeZone(TimeZone.getTimeZone("UTC"));
// Build up the hash tables to look up Exif tags for reading Exif tags.
for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) {
@@ -2140,7 +2152,8 @@
@UnsupportedAppUsage
public @CurrentTimeMillisLong long getDateTime() {
return parseDateTime(getAttribute(TAG_DATETIME),
- getAttribute(TAG_SUBSEC_TIME));
+ getAttribute(TAG_SUBSEC_TIME),
+ getAttribute(TAG_OFFSET_TIME));
}
/**
@@ -2151,7 +2164,8 @@
*/
public @CurrentTimeMillisLong long getDateTimeDigitized() {
return parseDateTime(getAttribute(TAG_DATETIME_DIGITIZED),
- getAttribute(TAG_SUBSEC_TIME_DIGITIZED));
+ getAttribute(TAG_SUBSEC_TIME_DIGITIZED),
+ getAttribute(TAG_OFFSET_TIME_DIGITIZED));
}
/**
@@ -2163,11 +2177,12 @@
@UnsupportedAppUsage
public @CurrentTimeMillisLong long getDateTimeOriginal() {
return parseDateTime(getAttribute(TAG_DATETIME_ORIGINAL),
- getAttribute(TAG_SUBSEC_TIME_ORIGINAL));
+ getAttribute(TAG_SUBSEC_TIME_ORIGINAL),
+ getAttribute(TAG_OFFSET_TIME_ORIGINAL));
}
private static @CurrentTimeMillisLong long parseDateTime(@Nullable String dateTimeString,
- @Nullable String subSecs) {
+ @Nullable String subSecs, @Nullable String offsetString) {
if (dateTimeString == null
|| !sNonZeroTimePattern.matcher(dateTimeString).matches()) return -1;
@@ -2176,6 +2191,13 @@
// The exif field is in local time. Parsing it as if it is UTC will yield time
// since 1/1/1970 local time
Date datetime = sFormatter.parse(dateTimeString, pos);
+
+ if (offsetString != null) {
+ dateTimeString = dateTimeString + " " + offsetString;
+ ParsePosition position = new ParsePosition(0);
+ datetime = sFormatterTz.parse(dateTimeString, position);
+ }
+
if (datetime == null) return -1;
long msecs = datetime.getTime();