1f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescupackage com.android.gallery3d.ingest.data; 2f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 3f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport android.annotation.TargetApi; 4f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport android.mtp.MtpConstants; 5f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport android.mtp.MtpDevice; 66669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chungimport android.mtp.MtpObjectInfo; 7f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport android.os.Build; 86669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chungimport android.webkit.MimeTypeMap; 9f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 10f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport java.util.Collections; 116669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chungimport java.util.HashMap; 12f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport java.util.HashSet; 136669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chungimport java.util.Locale; 146669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chungimport java.util.Map; 15f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport java.util.Set; 16f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 17f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu/** 18f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * Index of MTP media objects organized into "buckets," or groupings, based on the date 19f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * they were created. 20f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * 21f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * When the index is created, the buckets are sorted in their natural 22f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * order, and the items within the buckets sorted by the date they are taken. 23f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * 24f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * The index enables the access of items and bucket labels as one unified list. 25f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * For example, let's say we have the following data in the index: 26f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * [Bucket A]: [photo 1], [photo 2] 27f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * [Bucket B]: [photo 3] 28f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * 29f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * Then the items can be thought of as being organized as a 5 element list: 30f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * [Bucket A], [photo 1], [photo 2], [Bucket B], [photo 3] 31f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * 32f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * The data can also be accessed in descending order, in which case the list 33f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * would be a bit different from simply reversing the ascending list, since the 34f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * bucket labels need to always be at the beginning: 35f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * [Bucket B], [photo 3], [Bucket A], [photo 2], [photo 1] 36f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * 37f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * The index enables all the following operations in constant time, both for 38f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * ascending and descending views of the data: 39f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * - get/getAscending/getDescending: get an item at a specified list position 40f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * - size: get the total number of items (bucket labels and MTP objects) 41f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * - getFirstPositionForBucketNumber 42f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * - getBucketNumberForPosition 43f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * - isFirstInBucket 44f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * 45f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * See {@link MtpDeviceIndexRunnable} for implementation notes. 46f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 47f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) 48f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescupublic class MtpDeviceIndex { 49f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 50f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 51f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * Indexing progress listener. 52f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 53f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public interface ProgressListener { 54f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 55f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * A media item on the device was indexed. 56f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param object The media item that was just indexed 57f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param numVisited Number of items visited so far 58f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 59f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public void onObjectIndexed(IngestObjectInfo object, int numVisited); 60f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 61f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 62f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * The metadata loaded from the device is being sorted. 63f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 64f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public void onSortingStarted(); 65f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 66f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 67f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * The indexing is done and the index is ready to be used. 68f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 69f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public void onIndexingFinished(); 70f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 71f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 72f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 73f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * Media sort orders. 74f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 75f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public enum SortOrder { 76f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu ASCENDING, DESCENDING 77f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 78f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 79f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** Quicktime MOV container (not already defined in {@link MtpConstants}) **/ 80f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public static final int FORMAT_MOV = 0x300D; 81f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 82f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public static final Set<Integer> SUPPORTED_IMAGE_FORMATS; 83f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public static final Set<Integer> SUPPORTED_VIDEO_FORMATS; 84f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 85f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu static { 86f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu Set<Integer> supportedImageFormats = new HashSet<Integer>(); 87f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu supportedImageFormats.add(MtpConstants.FORMAT_JFIF); 88f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu supportedImageFormats.add(MtpConstants.FORMAT_EXIF_JPEG); 89f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu supportedImageFormats.add(MtpConstants.FORMAT_PNG); 90f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu supportedImageFormats.add(MtpConstants.FORMAT_GIF); 91f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu supportedImageFormats.add(MtpConstants.FORMAT_BMP); 926669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung supportedImageFormats.add(MtpConstants.FORMAT_TIFF); 936669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung supportedImageFormats.add(MtpConstants.FORMAT_TIFF_EP); 946669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung if (Build.VERSION.SDK_INT >= 24) { 956669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung supportedImageFormats.add(MtpConstants.FORMAT_DNG); 966669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung } 97f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu SUPPORTED_IMAGE_FORMATS = Collections.unmodifiableSet(supportedImageFormats); 98f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 99f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu Set<Integer> supportedVideoFormats = new HashSet<Integer>(); 100f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu supportedVideoFormats.add(MtpConstants.FORMAT_3GP_CONTAINER); 101f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu supportedVideoFormats.add(MtpConstants.FORMAT_AVI); 102f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu supportedVideoFormats.add(MtpConstants.FORMAT_MP4_CONTAINER); 1036669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung supportedVideoFormats.add(MtpConstants.FORMAT_MP2); 104f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu supportedVideoFormats.add(MtpConstants.FORMAT_MPEG); 105f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu // TODO(georgescu): add FORMAT_MOV once Android Media Scanner supports .mov files 106f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu SUPPORTED_VIDEO_FORMATS = Collections.unmodifiableSet(supportedVideoFormats); 107f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 108f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 109f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private MtpDevice mDevice; 110f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private long mGeneration; 111f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private ProgressListener mProgressListener; 112f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private volatile MtpDeviceIndexRunnable.Results mResults; 113f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private final MtpDeviceIndexRunnable.Factory mIndexRunnableFactory; 114f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 115f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private static final MtpDeviceIndex sInstance = new MtpDeviceIndex( 116f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.getFactory()); 117f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 1186669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung private static final Map<String, Boolean> sCachedSupportedExtenstions = new HashMap<>(); 1196669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung 120f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public static MtpDeviceIndex getInstance() { 121f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return sInstance; 122f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 123f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 124f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected MtpDeviceIndex(MtpDeviceIndexRunnable.Factory indexRunnableFactory) { 125f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mIndexRunnableFactory = indexRunnableFactory; 126f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 127f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 128f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public synchronized MtpDevice getDevice() { 129f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return mDevice; 130f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 131f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 132f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public synchronized boolean isDeviceConnected() { 133f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return (mDevice != null); 134f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 135f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 136f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 1376669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung * @param mtpObjectInfo MTP object info 138f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return Whether the format is supported by this index. 139f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 1406669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung public boolean isFormatSupported(MtpObjectInfo mtpObjectInfo) { 1416669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung // Checks whether the format is supported or not. 1426669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung final int format = mtpObjectInfo.getFormat(); 1436669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung if (SUPPORTED_IMAGE_FORMATS.contains(format) 1446669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung || SUPPORTED_VIDEO_FORMATS.contains(format)) { 1456669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung return true; 1466669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung } 1476669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung 1486669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung // Checks whether the extension is supported or not. 1496669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung final String name = mtpObjectInfo.getName(); 1506669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung if (name == null) { 1516669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung return false; 1526669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung } 1536669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung final int lastDot = name.lastIndexOf('.'); 1546669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung if (lastDot >= 0) { 1556669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung final String extension = name.substring(lastDot + 1); 1566669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung 1576669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung Boolean result = sCachedSupportedExtenstions.get(extension); 1586669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung if (result != null) { 1596669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung return result; 1606669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung } 1616669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension( 1626669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung extension.toLowerCase(Locale.US)); 1636669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung if (mime != null) { 1646669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung // This will also accept the newly added mimetypes for images and videos. 1656669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung result = mime.startsWith("image/") || mime.startsWith("video/"); 1666669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung sCachedSupportedExtenstions.put(extension, result); 1676669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung return result; 1686669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung } 1696669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung } 1706669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung 1716669f2c4e92da4ee45c0d23ebee38a2cf0e7f539Jaesung Chung return false; 172f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 173f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 174f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 175f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * Sets the MtpDevice that should be indexed and initializes state, but does 176f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * not kick off the actual indexing task, which is instead done by using 177f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * {@link #getIndexRunnable()} 178f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * 179f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param device The MtpDevice that should be indexed 180f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 181f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public synchronized void setDevice(MtpDevice device) { 182f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (device == mDevice) { 183f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return; 184f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 185f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mDevice = device; 186f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu resetState(); 187f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 188f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 189f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 190f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * Provides a Runnable for the indexing task (assuming the state has already 191f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * been correctly initialized by calling {@link #setDevice(MtpDevice)}). 192f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * 193f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return Runnable for the main indexing task 194f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 195f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public synchronized Runnable getIndexRunnable() { 196f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (!isDeviceConnected() || mResults != null) { 197f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return null; 198f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 199f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return mIndexRunnableFactory.createMtpDeviceIndexRunnable(this); 200f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 201f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 202f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 203f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return Whether the index is ready to be used. 204f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 205f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public synchronized boolean isIndexReady() { 206f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return mResults != null; 207f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 208f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 209f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 210f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param listener 211f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return Current progress (useful for configuring initial UI state) 212f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 213f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public synchronized void setProgressListener(ProgressListener listener) { 214f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mProgressListener = listener; 215f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 216f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 217f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 218f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * Make the listener null if it matches the argument 219f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * 220f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param listener Listener to unset, if currently registered 221f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 222f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public synchronized void unsetProgressListener(ProgressListener listener) { 223f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (mProgressListener == listener) { 224f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mProgressListener = null; 225f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 226f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 227f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 228f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 229f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return The total number of elements in the index (labels and items) 230f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 231f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public int size() { 232f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 233f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results != null ? results.unifiedLookupIndex.length : 0; 234f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 235f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 236f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 237f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param position Index of item to fetch, where 0 is the first item in the 238f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * specified order 239f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param order 240f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return the bucket label or IngestObjectInfo at the specified position and 241f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * order 242f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 243f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public Object get(int position, SortOrder order) { 244f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 245f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (results == null) { 246f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return null; 247f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 248f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (order == SortOrder.ASCENDING) { 249f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu DateBucket bucket = results.buckets[results.unifiedLookupIndex[position]]; 250f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (bucket.unifiedStartIndex == position) { 251f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return bucket.date; 252f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 253f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.mtpObjects[bucket.itemsStartIndex + position - 1 254f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu - bucket.unifiedStartIndex]; 255f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 256f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 257f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int zeroIndex = results.unifiedLookupIndex.length - 1 - position; 258f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu DateBucket bucket = results.buckets[results.unifiedLookupIndex[zeroIndex]]; 259f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (bucket.unifiedEndIndex == zeroIndex) { 260f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return bucket.date; 261f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 262f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.mtpObjects[bucket.itemsStartIndex + zeroIndex 263f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu - bucket.unifiedStartIndex]; 264f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 265f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 266f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 267f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 268f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 269f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param position Index of item to fetch from a view of the data that does not 270f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * include labels and is in the specified order 271f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return position-th item in specified order, when not including labels 272f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 273f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public IngestObjectInfo getWithoutLabels(int position, SortOrder order) { 274f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 275f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (results == null) { 276f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return null; 277f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 278f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (order == SortOrder.ASCENDING) { 279f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.mtpObjects[position]; 280f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 281f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.mtpObjects[results.mtpObjects.length - 1 - position]; 282f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 283f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 284f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 285f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 286f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param position Index of item to map from a view of the data that does not 287f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * include labels and is in the specified order 288f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param order 289f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return position in a view of the data that does include labels, or -1 if the index isn't 290f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * ready 291f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 292f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public int getPositionFromPositionWithoutLabels(int position, SortOrder order) { 293f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /* Although this is O(log(number of buckets)), and thus should not be used 294f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu in hotspots, even if the attached device has items for every day for 295f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu a five-year timeframe, it would still only take 11 iterations at most, 296f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu so shouldn't be a huge issue. */ 297f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 298f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (results == null) { 299f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return -1; 300f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 301f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (order == SortOrder.DESCENDING) { 302f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu position = results.mtpObjects.length - 1 - position; 303f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 304f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int bucketNumber = 0; 305f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int iMin = 0; 306f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int iMax = results.buckets.length - 1; 307f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu while (iMax >= iMin) { 308f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int iMid = (iMax + iMin) / 2; 309f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (results.buckets[iMid].itemsStartIndex + results.buckets[iMid].numItems 310f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu <= position) { 311f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu iMin = iMid + 1; 312f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else if (results.buckets[iMid].itemsStartIndex > position) { 313f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu iMax = iMid - 1; 314f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 315f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu bucketNumber = iMid; 316f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu break; 317f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 318f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 319f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int mappedPos = results.buckets[bucketNumber].unifiedStartIndex + position 320f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu - results.buckets[bucketNumber].itemsStartIndex + 1; 321f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (order == SortOrder.DESCENDING) { 322f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mappedPos = results.unifiedLookupIndex.length - mappedPos; 323f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 324f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return mappedPos; 325f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 326f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 327f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 328f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param position Index of item to map from a view of the data that 329f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * includes labels and is in the specified order 330f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param order 331f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return position in a view of the data that does not include labels, or -1 if the index isn't 332f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * ready 333f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 334f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public int getPositionWithoutLabelsFromPosition(int position, SortOrder order) { 335f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 336f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (results == null) { 337f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return -1; 338f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 339f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (order == SortOrder.ASCENDING) { 340f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu DateBucket bucket = results.buckets[results.unifiedLookupIndex[position]]; 341f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (bucket.unifiedStartIndex == position) { 342f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu position++; 343f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 344f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return bucket.itemsStartIndex + position - 1 - bucket.unifiedStartIndex; 345f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 346f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int zeroIndex = results.unifiedLookupIndex.length - 1 - position; 347f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu DateBucket bucket = results.buckets[results.unifiedLookupIndex[zeroIndex]]; 348f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (bucket.unifiedEndIndex == zeroIndex) { 349f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu zeroIndex--; 350f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 351f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.mtpObjects.length - 1 - bucket.itemsStartIndex 352f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu - zeroIndex + bucket.unifiedStartIndex; 353f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 354f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 355f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 356f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 357f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return The number of media items in the index 358f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 359f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public int sizeWithoutLabels() { 360f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 361f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results != null ? results.mtpObjects.length : 0; 362f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 363f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 364f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 365f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param bucketNumber Index of bucket in the specified order 366f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param order 367f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return position of bucket's first item in a view of the data that includes labels 368f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 369f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public int getFirstPositionForBucketNumber(int bucketNumber, SortOrder order) { 370f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 371f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (order == SortOrder.ASCENDING) { 372f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.buckets[bucketNumber].unifiedStartIndex; 373f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 374f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.unifiedLookupIndex.length 375f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu - results.buckets[results.buckets.length - 1 - bucketNumber].unifiedEndIndex 376f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu - 1; 377f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 378f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 379f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 380f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 381f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param position Index of item in the view of the data that includes labels and is in 382f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * the specified order 383f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param order 384f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return Index of the bucket that contains the specified item 385f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 386f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public int getBucketNumberForPosition(int position, SortOrder order) { 387f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 388f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (order == SortOrder.ASCENDING) { 389f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.unifiedLookupIndex[position]; 390f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 391f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.buckets.length - 1 392f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu - results.unifiedLookupIndex[results.unifiedLookupIndex.length - 1 393f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu - position]; 394f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 395f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 396f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 397f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 398f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param position Index of item in the view of the data that includes labels and is in 399f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * the specified order 400f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param order 401f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return Whether the specified item is the first item in its bucket 402f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 403f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public boolean isFirstInBucket(int position, SortOrder order) { 404f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 405f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (order == SortOrder.ASCENDING) { 406f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.buckets[results.unifiedLookupIndex[position]].unifiedStartIndex 407f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu == position; 408f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 409f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu position = results.unifiedLookupIndex.length - 1 - position; 410f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return results.buckets[results.unifiedLookupIndex[position]].unifiedEndIndex 411f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu == position; 412f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 413f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 414f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 415f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 416f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param order 417f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return Array of buckets in the specified order 418f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 419f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public DateBucket[] getBuckets(SortOrder order) { 420f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results = mResults; 421f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (results == null) { 422f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return null; 423f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 424f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return (order == SortOrder.ASCENDING) ? results.buckets : results.reversedBuckets; 425f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 426f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 427f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected void resetState() { 428f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mGeneration++; 429f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mResults = null; 430f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 431f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 432f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu /** 433f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param device 434f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @param generation 435f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * @return whether the index is at the given generation and the given device is connected 436f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 437f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected boolean isAtGeneration(MtpDevice device, long generation) { 438f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return (mGeneration == generation) && (mDevice == device); 439f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 440f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 441f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected synchronized boolean setIndexingResults(MtpDevice device, long generation, 442f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDeviceIndexRunnable.Results results) { 443f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (!isAtGeneration(device, generation)) { 444f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return false; 445f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 446f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mResults = results; 447f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu onIndexFinish(true /*successful*/); 448f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return true; 449f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 450f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 451f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected synchronized void onIndexFinish(boolean successful) { 452f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (!successful) { 453f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu resetState(); 454f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 455f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (mProgressListener != null) { 456f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mProgressListener.onIndexingFinished(); 457f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 458f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 459f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 460f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected synchronized void onSorting() { 461f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (mProgressListener != null) { 462f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mProgressListener.onSortingStarted(); 463f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 464f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 465f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 466f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected synchronized void onObjectIndexed(IngestObjectInfo object, int numVisited) { 467f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (mProgressListener != null) { 468f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mProgressListener.onObjectIndexed(object, numVisited); 469f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 470f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 471f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 472f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected long getGeneration() { 473f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return mGeneration; 474f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 475f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu} 476