blob: 0307b94a433ae0383d8d60dfe7eaf197b95b9ff0 [file] [log] [blame]
/*
* Copyright (C) 2017 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 com.android.documentsui.inspector;
import static androidx.core.util.Preconditions.checkNotNull;
import android.media.ExifInterface;
import android.os.Bundle;
import android.provider.DocumentsContract;
import com.android.documentsui.base.Shared;
import javax.annotation.Nullable;
final class MetadataUtils {
private MetadataUtils() {}
static boolean hasGeoCoordinates(@Nullable Bundle metadata) {
if (metadata == null) {
return false;
}
return hasVideoCoordinates(metadata.getBundle(Shared.METADATA_KEY_VIDEO))
|| hasExifGpsFields(metadata.getBundle(DocumentsContract.METADATA_EXIF));
}
static boolean hasVideoCoordinates(@Nullable Bundle data) {
return data != null && (data.containsKey(Shared.METADATA_VIDEO_LATITUDE)
&& data.containsKey(Shared.METADATA_VIDEO_LONGITUTE));
}
static boolean hasExifGpsFields(@Nullable Bundle exif) {
return exif != null && (exif.containsKey(ExifInterface.TAG_GPS_LATITUDE)
&& exif.containsKey(ExifInterface.TAG_GPS_LONGITUDE)
&& exif.containsKey(ExifInterface.TAG_GPS_LATITUDE_REF)
&& exif.containsKey(ExifInterface.TAG_GPS_LONGITUDE_REF));
}
static float[] getGeoCoordinates(Bundle metadata) {
assert hasGeoCoordinates(metadata);
checkNotNull(metadata);
Bundle bundle = metadata.getBundle(DocumentsContract.METADATA_EXIF);
if (hasExifGpsFields(bundle)) {
return getExifGpsCoords(bundle);
}
bundle = metadata.getBundle(Shared.METADATA_KEY_VIDEO);
if (hasVideoCoordinates(bundle)) {
return getVideoCoords(bundle);
}
// This should never happen, because callers should always check w/ hasGeoCoordinates first.
throw new IllegalArgumentException("Invalid metadata bundle: " + metadata);
}
static float[] getExifGpsCoords(Bundle exif) {
assert hasExifGpsFields(exif);
String lat = exif.getString(ExifInterface.TAG_GPS_LATITUDE);
String lon = exif.getString(ExifInterface.TAG_GPS_LONGITUDE);
String latRef = exif.getString(ExifInterface.TAG_GPS_LATITUDE_REF);
String lonRef = exif.getString(ExifInterface.TAG_GPS_LONGITUDE_REF);
return new float[] {
convertRationalLatLonToFloat(lat, latRef), convertRationalLatLonToFloat(lon, lonRef)
};
}
static float[] getVideoCoords(Bundle data) {
assert hasVideoCoordinates(data);
return new float[] {
data.getFloat(Shared.METADATA_VIDEO_LATITUDE),
data.getFloat(Shared.METADATA_VIDEO_LONGITUTE)
};
}
/** This founction is copied from {@link ExifInterface} */
private static float convertRationalLatLonToFloat(String rationalString, String ref) {
try {
String [] parts = rationalString.split(",");
String [] pair;
pair = parts[0].split("/");
double degrees = Double.parseDouble(pair[0].trim())
/ Double.parseDouble(pair[1].trim());
pair = parts[1].split("/");
double minutes = Double.parseDouble(pair[0].trim())
/ Double.parseDouble(pair[1].trim());
pair = parts[2].split("/");
double seconds = Double.parseDouble(pair[0].trim())
/ Double.parseDouble(pair[1].trim());
double result = degrees + (minutes / 60.0) + (seconds / 3600.0);
if ((ref.equals("S") || ref.equals("W"))) {
return (float) -result;
}
return (float) result;
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
// Not valid
throw new IllegalArgumentException();
}
}
}