OSDN Git Service

Workaround for future GPS timestamps
authorAlan Newberger <alann@google.com>
Tue, 10 Mar 2015 17:29:11 +0000 (10:29 -0700)
committerAlan Newberger <alann@google.com>
Tue, 10 Mar 2015 20:58:34 +0000 (13:58 -0700)
Some images are known to have incorrect GPS timestamps, which are used
by MediaStore as creation date. If future creation dates are encountered,
fall back to modification date which is not known to have bugs.

Bug: 19565464
Change-Id: I35b5e43c9a3de1f05d9a2f405502a2bb2bf9adde

src/com/android/camera/data/CameraFilmstripDataAdapter.java
src/com/android/camera/data/NewestFirstComparator.java

index 3457522..8a52119 100644 (file)
@@ -30,6 +30,7 @@ import com.google.common.base.Optional;
 
 import java.util.ArrayList;
 import java.util.Comparator;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -257,7 +258,8 @@ public class CameraFilmstripDataAdapter implements LocalFilmstripDataAdapter {
         // a simple linear search should yield the best performance over a
         // binary search.
         int pos = 0;
-        Comparator<FilmstripItem> comp = new NewestFirstComparator();
+        Comparator<FilmstripItem> comp = new NewestFirstComparator(
+                new Date());
         for (; pos < mFilmstripItems.size()
                 && comp.compare(item, mFilmstripItems.get(pos)) > 0; pos++) {
         }
@@ -426,7 +428,7 @@ public class CameraFilmstripDataAdapter implements LocalFilmstripDataAdapter {
             // Photos should be sorted within photo/video by ID, which in most
             // cases should correlate well to the date taken/modified. This sort
             // operation makes all photos/videos sorted by date in one list.
-            l.sort(new NewestFirstComparator());
+            l.sort(new NewestFirstComparator(new Date()));
             Log.v(TAG, "sorted video/photo metadata");
 
             // Load enough metadata so it's already loaded when we open the filmstrip.
index c172f5c..11a6011 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.camera.data;
 
+import com.google.common.base.Preconditions;
+
 import java.util.Comparator;
 import java.util.Date;
 
@@ -24,12 +26,36 @@ import java.util.Date;
  * then by title comparison.
  */
 public class NewestFirstComparator implements Comparator<FilmstripItem> {
+    private final Date mNow;
+
+    private static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
+
+    /**
+     * Construct a comparator that sorts items by newest first. We ignore future
+     * creation dates using the supplied current date as a baseline.
+     *
+     * @param now present date to be used in comparisons to rule out dates in
+     *            the future.
+     */
+    public NewestFirstComparator(Date now) {
+        Preconditions.checkNotNull(now);
+        // Buffer by 24 hours to protect against false positives due to intraday
+        // time zone issues.
+        mNow = new Date(now.getTime() + MILLIS_IN_DAY);
+    }
+
     @Override
     public int compare(FilmstripItem d1, FilmstripItem d2) {
         FilmstripItemData d1Data = d1.getData();
         FilmstripItemData d2Data = d2.getData();
-        int cmp = compareDate(d1Data.getCreationDate(),
-              d2Data.getCreationDate());
+
+        // If creation date is in future, fall back to modified, b/19565464.
+        Date d1PrimaryDate = isFuture(d1Data.getCreationDate()) ?
+                d1Data.getLastModifiedDate() : d1Data.getCreationDate();
+        Date d2PrimaryDate = isFuture(d2Data.getCreationDate()) ?
+                d2Data.getLastModifiedDate() : d2Data.getCreationDate();
+
+        int cmp = compareDate(d1PrimaryDate, d2PrimaryDate);
         if (cmp == 0) {
             cmp = compareDate(d1Data.getLastModifiedDate(),
                   d2Data.getLastModifiedDate());
@@ -44,7 +70,19 @@ public class NewestFirstComparator implements Comparator<FilmstripItem> {
      * Normal date comparison will sort these oldest first,
      * so invert the order by multiplying by -1.
      */
-    private static int compareDate(Date v1, Date v2) {
+    private int compareDate(Date v1, Date v2) {
         return v1.compareTo(v2) * -1;
     }
+
+    /**
+     * Is the Date in the future from a base date. If the date is in the future
+     * (larger) than the base date provided, return true.
+     *
+     * @param date The date to check whether it is in the future
+     * @param base The date to use as a baseline 'present'
+     * @return true if date is in the future from base
+     */
+    private boolean isFuture(Date date) {
+        return mNow.compareTo(date) < 0;
+    }
 }
\ No newline at end of file