@Override
    public void onFutureDone(final Future<File> future) {
      final File file = future.get();
      long id = 0;
      if (file != null) { // insert to database
        id = insertEntry(mUrl, file);
      }

      if (future.isCancelled()) {
        Utils.assertTrue(mProxySet.isEmpty());
        return;
      }

      synchronized (mTaskMap) {
        Entry entry = null;
        synchronized (mEntryMap) {
          if (file != null) {
            entry = new Entry(id, file);
            Utils.assertTrue(mEntryMap.put(mUrl, entry) == null);
          }
        }
        for (final TaskProxy proxy : mProxySet) {
          proxy.setResult(entry);
        }
        mTaskMap.remove(mUrl);
        freeSomeSpaceIfNeed(MAX_DELETE_COUNT);
      }
    }
 private Entry findEntryInDatabase(final String stringUrl) {
   final long hash = Utils.crc64Long(stringUrl);
   final String whereArgs[] = {String.valueOf(hash), stringUrl};
   final Cursor cursor =
       mDatabase.query(
           TABLE_NAME, QUERY_PROJECTION, WHERE_HASH_AND_URL, whereArgs, null, null, null);
   try {
     if (cursor.moveToNext()) {
       final File file = new File(cursor.getString(QUERY_INDEX_DATA));
       final long id = cursor.getInt(QUERY_INDEX_ID);
       Entry entry = null;
       synchronized (mEntryMap) {
         entry = mEntryMap.get(stringUrl);
         if (entry == null) {
           entry = new Entry(id, file);
           mEntryMap.put(stringUrl, entry);
         }
       }
       return entry;
     }
   } finally {
     cursor.close();
   }
   return null;
 }
 public void removeProxy(final TaskProxy proxy) {
   synchronized (mTaskMap) {
     Utils.assertTrue(mProxySet.remove(proxy));
     if (mProxySet.isEmpty()) {
       mFuture.cancel();
       mTaskMap.remove(mUrl);
     }
   }
 }
  private synchronized long insertEntry(final String url, final File file) {
    final long size = file.length();
    mTotalBytes += size;

    final ContentValues values = new ContentValues();
    final String hashCode = String.valueOf(Utils.crc64Long(url));
    values.put(Columns.DATA, file.getAbsolutePath());
    values.put(Columns.HASH_CODE, hashCode);
    values.put(Columns.CONTENT_URL, url);
    values.put(Columns.CONTENT_SIZE, size);
    values.put(Columns.LAST_UPDATED, System.currentTimeMillis());
    return mDatabase.insert(TABLE_NAME, "", values);
  }
 public boolean calculate(final long currentTimeMillis) {
   if (mStartTime == NO_ANIMATION) return false;
   if (mStartTime == ANIMATION_START) {
     mStartTime = currentTimeMillis;
   }
   final int elapse = (int) (currentTimeMillis - mStartTime);
   final float x = Utils.clamp((float) elapse / mDuration, 0f, 1f);
   final Interpolator i = mInterpolator;
   onCalculate(i != null ? i.getInterpolation(x) : x);
   if (elapse >= mDuration) {
     mStartTime = NO_ANIMATION;
   }
   return mStartTime != NO_ANIMATION;
 }
 public DownloadCache(final GalleryApp application, final File root, final long capacity) {
   mRoot = Utils.checkNotNull(root);
   mApplication = Utils.checkNotNull(application);
   mCapacity = capacity;
   mDatabase = new DatabaseHelper(application.getAndroidContext()).getWritableDatabase();
 }
 public DownloadTask(final String url) {
   mUrl = Utils.checkNotNull(url);
 }
 Entry(final long id, final File cacheFile) {
   mId = id;
   this.cacheFile = Utils.checkNotNull(cacheFile);
 }