summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads/DownloadThread.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/providers/downloads/DownloadThread.java')
-rw-r--r--src/com/android/providers/downloads/DownloadThread.java219
1 files changed, 126 insertions, 93 deletions
diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java
index 3cc8c22b..7703d14d 100644
--- a/src/com/android/providers/downloads/DownloadThread.java
+++ b/src/com/android/providers/downloads/DownloadThread.java
@@ -16,23 +16,19 @@
package com.android.providers.downloads;
-import org.apache.http.client.methods.AbortableHttpRequest;
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.HttpClient;
import org.apache.http.entity.StringEntity;
-import org.apache.http.Header;
-import org.apache.http.HttpResponse;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.database.Cursor;
import android.drm.mobile1.DrmRawContent;
-import android.net.http.AndroidHttpClient;
import android.net.Uri;
+import android.net.http.AndroidHttpClient;
import android.os.FileUtils;
import android.os.PowerManager;
import android.os.Process;
@@ -42,12 +38,14 @@ import android.util.Config;
import android.util.Log;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
-import java.io.InputStream;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
+import java.io.InputStream;
+import java.io.SyncFailedException;
import java.net.URI;
+import java.net.URISyntaxException;
import java.util.Locale;
/**
@@ -67,7 +65,7 @@ public class DownloadThread extends Thread {
* Returns the user agent provided by the initiating app, or use the default one
*/
private String userAgent() {
- String userAgent = mInfo.userAgent;
+ String userAgent = mInfo.mUserAgent;
if (userAgent != null) {
}
if (userAgent == null) {
@@ -85,15 +83,15 @@ public class DownloadThread extends Thread {
int finalStatus = Downloads.STATUS_UNKNOWN_ERROR;
boolean countRetry = false;
int retryAfter = 0;
- int redirectCount = mInfo.redirectCount;
+ int redirectCount = mInfo.mRedirectCount;
String newUri = null;
boolean gotData = false;
String filename = null;
- String mimeType = sanitizeMimeType(mInfo.mimetype);
+ String mimeType = sanitizeMimeType(mInfo.mMimeType);
FileOutputStream stream = null;
AndroidHttpClient client = null;
PowerManager.WakeLock wakeLock = null;
- Uri contentUri = Uri.parse(Downloads.CONTENT_URI + "/" + mInfo.id);
+ Uri contentUri = Uri.parse(Downloads.CONTENT_URI + "/" + mInfo.mId);
try {
boolean continuingDownload = false;
@@ -112,12 +110,12 @@ public class DownloadThread extends Thread {
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG);
wakeLock.acquire();
- filename = mInfo.filename;
+ filename = mInfo.mFileName;
if (filename != null) {
if (!Helpers.isFilenameValid(filename)) {
finalStatus = Downloads.STATUS_FILE_ERROR;
notifyDownloadCompleted(
- finalStatus, false, 0, 0, false, filename, null, mInfo.mimetype);
+ finalStatus, false, 0, 0, false, filename, null, mInfo.mMimeType);
return;
}
// We're resuming a download that got interrupted
@@ -128,7 +126,7 @@ public class DownloadThread extends Thread {
// The download hadn't actually started, we can restart from scratch
f.delete();
filename = null;
- } else if (mInfo.etag == null && !mInfo.noIntegrity) {
+ } else if (mInfo.mETag == null && !mInfo.mNoIntegrity) {
// Tough luck, that's not a resumable download
if (Config.LOGD) {
Log.d(Constants.TAG,
@@ -137,16 +135,16 @@ public class DownloadThread extends Thread {
f.delete();
finalStatus = Downloads.STATUS_PRECONDITION_FAILED;
notifyDownloadCompleted(
- finalStatus, false, 0, 0, false, filename, null, mInfo.mimetype);
+ finalStatus, false, 0, 0, false, filename, null, mInfo.mMimeType);
return;
} else {
// All right, we'll be able to resume this download
stream = new FileOutputStream(filename, true);
bytesSoFar = (int) fileLength;
- if (mInfo.totalBytes != -1) {
- headerContentLength = Integer.toString(mInfo.totalBytes);
+ if (mInfo.mTotalBytes != -1) {
+ headerContentLength = Integer.toString(mInfo.mTotalBytes);
}
- headerETag = mInfo.etag;
+ headerETag = mInfo.mETag;
continuingDownload = true;
}
}
@@ -159,7 +157,7 @@ public class DownloadThread extends Thread {
client = AndroidHttpClient.newInstance(userAgent());
- if (stream != null && mInfo.destination == Downloads.DESTINATION_EXTERNAL
+ if (stream != null && mInfo.mDestination == Downloads.DESTINATION_EXTERNAL
&& !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING
.equalsIgnoreCase(mimeType)) {
try {
@@ -182,17 +180,17 @@ public class DownloadThread extends Thread {
http_request_loop:
while (true) {
// Prepares the request and fires it.
- HttpGet request = new HttpGet(mInfo.uri);
+ HttpGet request = new HttpGet(mInfo.mUri);
if (Constants.LOGV) {
- Log.v(Constants.TAG, "initiating download for " + mInfo.uri);
+ Log.v(Constants.TAG, "initiating download for " + mInfo.mUri);
}
- if (mInfo.cookies != null) {
- request.addHeader("Cookie", mInfo.cookies);
+ if (mInfo.mCookies != null) {
+ request.addHeader("Cookie", mInfo.mCookies);
}
- if (mInfo.referer != null) {
- request.addHeader("Referer", mInfo.referer);
+ if (mInfo.mReferer != null) {
+ request.addHeader("Referer", mInfo.mReferer);
}
if (continuingDownload) {
if (headerETag != null) {
@@ -207,10 +205,10 @@ http_request_loop:
} catch (IllegalArgumentException ex) {
if (Constants.LOGV) {
Log.d(Constants.TAG, "Arg exception trying to execute request for " +
- mInfo.uri + " : " + ex);
+ mInfo.mUri + " : " + ex);
} else if (Config.LOGD) {
Log.d(Constants.TAG, "Arg exception trying to execute request for " +
- mInfo.id + " : " + ex);
+ mInfo.mId + " : " + ex);
}
finalStatus = Downloads.STATUS_BAD_REQUEST;
request.abort();
@@ -218,16 +216,16 @@ http_request_loop:
} catch (IOException ex) {
if (!Helpers.isNetworkAvailable(mContext)) {
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
- } else if (mInfo.numFailed < Constants.MAX_RETRIES) {
+ } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
countRetry = true;
} else {
if (Constants.LOGV) {
Log.d(Constants.TAG, "IOException trying to execute request for " +
- mInfo.uri + " : " + ex);
+ mInfo.mUri + " : " + ex);
} else if (Config.LOGD) {
Log.d(Constants.TAG, "IOException trying to execute request for " +
- mInfo.id + " : " + ex);
+ mInfo.mId + " : " + ex);
}
finalStatus = Downloads.STATUS_HTTP_DATA_ERROR;
}
@@ -236,7 +234,7 @@ http_request_loop:
}
int statusCode = response.getStatusLine().getStatusCode();
- if (statusCode == 503 && mInfo.numFailed < Constants.MAX_RETRIES) {
+ if (statusCode == 503 && mInfo.mNumFailed < Constants.MAX_RETRIES) {
if (Constants.LOGVV) {
Log.v(Constants.TAG, "got HTTP response code 503");
}
@@ -257,7 +255,7 @@ http_request_loop:
} else if (retryAfter > Constants.MAX_RETRY_AFTER) {
retryAfter = Constants.MAX_RETRY_AFTER;
}
- retryAfter += Helpers.rnd.nextInt(Constants.MIN_RETRY_AFTER + 1);
+ retryAfter += Helpers.sRandom.nextInt(Constants.MIN_RETRY_AFTER + 1);
retryAfter *= 1000;
}
} catch (NumberFormatException ex) {
@@ -276,10 +274,10 @@ http_request_loop:
}
if (redirectCount >= Constants.MAX_REDIRECTS) {
if (Constants.LOGV) {
- Log.d(Constants.TAG, "too many redirects for download " + mInfo.id +
- " at " + mInfo.uri);
+ Log.d(Constants.TAG, "too many redirects for download " + mInfo.mId +
+ " at " + mInfo.mUri);
} else if (Config.LOGD) {
- Log.d(Constants.TAG, "too many redirects for download " + mInfo.id);
+ Log.d(Constants.TAG, "too many redirects for download " + mInfo.mId);
}
finalStatus = Downloads.STATUS_TOO_MANY_REDIRECTS;
request.abort();
@@ -290,7 +288,26 @@ http_request_loop:
if (Constants.LOGVV) {
Log.v(Constants.TAG, "Location :" + header.getValue());
}
- newUri = new URI(mInfo.uri).resolve(new URI(header.getValue())).toString();
+ try {
+ newUri = new URI(mInfo.mUri).
+ resolve(new URI(header.getValue())).
+ toString();
+ } catch(URISyntaxException ex) {
+ if (Constants.LOGV) {
+ Log.d(Constants.TAG,
+ "Couldn't resolve redirect URI " +
+ header.getValue() +
+ " for " +
+ mInfo.mUri);
+ } else if (Config.LOGD) {
+ Log.d(Constants.TAG,
+ "Couldn't resolve redirect URI for download " +
+ mInfo.mId);
+ }
+ finalStatus = Downloads.STATUS_BAD_REQUEST;
+ request.abort();
+ break http_request_loop;
+ }
++redirectCount;
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
request.abort();
@@ -300,10 +317,10 @@ http_request_loop:
if ((!continuingDownload && statusCode != Downloads.STATUS_SUCCESS)
|| (continuingDownload && statusCode != 206)) {
if (Constants.LOGV) {
- Log.d(Constants.TAG, "http error " + statusCode + " for " + mInfo.uri);
+ Log.d(Constants.TAG, "http error " + statusCode + " for " + mInfo.mUri);
} else if (Config.LOGD) {
Log.d(Constants.TAG, "http error " + statusCode + " for download " +
- mInfo.id);
+ mInfo.mId);
}
if (Downloads.isStatusError(statusCode)) {
finalStatus = statusCode;
@@ -319,7 +336,7 @@ http_request_loop:
} else {
// Handles the response, saves the file
if (Constants.LOGV) {
- Log.v(Constants.TAG, "received response for " + mInfo.uri);
+ Log.v(Constants.TAG, "received response for " + mInfo.mUri);
}
if (!continuingDownload) {
@@ -372,7 +389,7 @@ http_request_loop:
Log.v(Constants.TAG, "Transfer-Encoding: " + headerTransferEncoding);
}
- if (!mInfo.noIntegrity && headerContentLength == null &&
+ if (!mInfo.mNoIntegrity && headerContentLength == null &&
(headerTransferEncoding == null
|| !headerTransferEncoding.equalsIgnoreCase("chunked"))
) {
@@ -386,23 +403,23 @@ http_request_loop:
DownloadFileInfo fileInfo = Helpers.generateSaveFile(
mContext,
- mInfo.uri,
- mInfo.hint,
+ mInfo.mUri,
+ mInfo.mHint,
headerContentDisposition,
headerContentLocation,
mimeType,
- mInfo.destination,
+ mInfo.mDestination,
(headerContentLength != null) ?
Integer.parseInt(headerContentLength) : 0);
- if (fileInfo.filename == null) {
- finalStatus = fileInfo.status;
+ if (fileInfo.mFileName == null) {
+ finalStatus = fileInfo.mStatus;
request.abort();
break http_request_loop;
}
- filename = fileInfo.filename;
- stream = fileInfo.stream;
+ filename = fileInfo.mFileName;
+ stream = fileInfo.mStream;
if (Constants.LOGV) {
- Log.v(Constants.TAG, "writing " + mInfo.uri + " to " + filename);
+ Log.v(Constants.TAG, "writing " + mInfo.mUri + " to " + filename);
}
ContentValues values = new ContentValues();
@@ -411,13 +428,13 @@ http_request_loop:
values.put(Constants.ETAG, headerETag);
}
if (mimeType != null) {
- values.put(Downloads.MIMETYPE, mimeType);
+ values.put(Downloads.COLUMN_MIME_TYPE, mimeType);
}
int contentLength = -1;
if (headerContentLength != null) {
contentLength = Integer.parseInt(headerContentLength);
}
- values.put(Downloads.TOTAL_BYTES, contentLength);
+ values.put(Downloads.COLUMN_TOTAL_BYTES, contentLength);
mContext.getContentResolver().update(contentUri, values, null, null);
}
@@ -427,16 +444,19 @@ http_request_loop:
} catch (IOException ex) {
if (!Helpers.isNetworkAvailable(mContext)) {
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
- } else if (mInfo.numFailed < Constants.MAX_RETRIES) {
+ } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
countRetry = true;
} else {
if (Constants.LOGV) {
- Log.d(Constants.TAG, "IOException getting entity for " + mInfo.uri +
- " : " + ex);
+ Log.d(Constants.TAG,
+ "IOException getting entity for " +
+ mInfo.mUri +
+ " : " +
+ ex);
} else if (Config.LOGD) {
Log.d(Constants.TAG, "IOException getting entity for download " +
- mInfo.id + " : " + ex);
+ mInfo.mId + " : " + ex);
}
finalStatus = Downloads.STATUS_HTTP_DATA_ERROR;
}
@@ -449,15 +469,15 @@ http_request_loop:
bytesRead = entityStream.read(data);
} catch (IOException ex) {
ContentValues values = new ContentValues();
- values.put(Downloads.CURRENT_BYTES, bytesSoFar);
+ values.put(Downloads.COLUMN_CURRENT_BYTES, bytesSoFar);
mContext.getContentResolver().update(contentUri, values, null, null);
- if (!mInfo.noIntegrity && headerETag == null) {
+ if (!mInfo.mNoIntegrity && headerETag == null) {
if (Constants.LOGV) {
- Log.v(Constants.TAG, "download IOException for " + mInfo.uri +
+ Log.v(Constants.TAG, "download IOException for " + mInfo.mUri +
" : " + ex);
} else if (Config.LOGD) {
Log.d(Constants.TAG, "download IOException for download " +
- mInfo.id + " : " + ex);
+ mInfo.mId + " : " + ex);
}
if (Config.LOGD) {
Log.d(Constants.TAG,
@@ -466,16 +486,16 @@ http_request_loop:
finalStatus = Downloads.STATUS_PRECONDITION_FAILED;
} else if (!Helpers.isNetworkAvailable(mContext)) {
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
- } else if (mInfo.numFailed < Constants.MAX_RETRIES) {
+ } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
countRetry = true;
} else {
if (Constants.LOGV) {
- Log.v(Constants.TAG, "download IOException for " + mInfo.uri +
+ Log.v(Constants.TAG, "download IOException for " + mInfo.mUri +
" : " + ex);
} else if (Config.LOGD) {
Log.d(Constants.TAG, "download IOException for download " +
- mInfo.id + " : " + ex);
+ mInfo.mId + " : " + ex);
}
finalStatus = Downloads.STATUS_HTTP_DATA_ERROR;
}
@@ -484,34 +504,34 @@ http_request_loop:
}
if (bytesRead == -1) { // success
ContentValues values = new ContentValues();
- values.put(Downloads.CURRENT_BYTES, bytesSoFar);
+ values.put(Downloads.COLUMN_CURRENT_BYTES, bytesSoFar);
if (headerContentLength == null) {
- values.put(Downloads.TOTAL_BYTES, bytesSoFar);
+ values.put(Downloads.COLUMN_TOTAL_BYTES, bytesSoFar);
}
mContext.getContentResolver().update(contentUri, values, null, null);
if ((headerContentLength != null)
&& (bytesSoFar
!= Integer.parseInt(headerContentLength))) {
- if (!mInfo.noIntegrity && headerETag == null) {
+ if (!mInfo.mNoIntegrity && headerETag == null) {
if (Constants.LOGV) {
Log.d(Constants.TAG, "mismatched content length " +
- mInfo.uri);
+ mInfo.mUri);
} else if (Config.LOGD) {
Log.d(Constants.TAG, "mismatched content length for " +
- mInfo.id);
+ mInfo.mId);
}
finalStatus = Downloads.STATUS_LENGTH_REQUIRED;
} else if (!Helpers.isNetworkAvailable(mContext)) {
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
- } else if (mInfo.numFailed < Constants.MAX_RETRIES) {
+ } else if (mInfo.mNumFailed < Constants.MAX_RETRIES) {
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
countRetry = true;
} else {
if (Constants.LOGV) {
- Log.v(Constants.TAG, "closed socket for " + mInfo.uri);
+ Log.v(Constants.TAG, "closed socket for " + mInfo.mUri);
} else if (Config.LOGD) {
Log.d(Constants.TAG, "closed socket for download " +
- mInfo.id);
+ mInfo.mId);
}
finalStatus = Downloads.STATUS_HTTP_DATA_ERROR;
}
@@ -526,7 +546,7 @@ http_request_loop:
stream = new FileOutputStream(filename, true);
}
stream.write(data, 0, bytesRead);
- if (mInfo.destination == Downloads.DESTINATION_EXTERNAL
+ if (mInfo.mDestination == Downloads.DESTINATION_EXTERNAL
&& !DrmRawContent.DRM_MIMETYPE_MESSAGE_STRING
.equalsIgnoreCase(mimeType)) {
try {
@@ -556,7 +576,7 @@ http_request_loop:
&& now - timeLastNotification
> Constants.MIN_PROGRESS_TIME) {
ContentValues values = new ContentValues();
- values.put(Downloads.CURRENT_BYTES, bytesSoFar);
+ values.put(Downloads.COLUMN_CURRENT_BYTES, bytesSoFar);
mContext.getContentResolver().update(
contentUri, values, null, null);
bytesNotified = bytesSoFar;
@@ -564,30 +584,30 @@ http_request_loop:
}
if (Constants.LOGVV) {
- Log.v(Constants.TAG, "downloaded " + bytesSoFar + " for " + mInfo.uri);
+ Log.v(Constants.TAG, "downloaded " + bytesSoFar + " for " + mInfo.mUri);
}
- synchronized(mInfo) {
- if (mInfo.control == Downloads.CONTROL_PAUSED) {
+ synchronized (mInfo) {
+ if (mInfo.mControl == Downloads.CONTROL_PAUSED) {
if (Constants.LOGV) {
- Log.v(Constants.TAG, "paused " + mInfo.uri);
+ Log.v(Constants.TAG, "paused " + mInfo.mUri);
}
finalStatus = Downloads.STATUS_RUNNING_PAUSED;
request.abort();
break http_request_loop;
}
}
- if (mInfo.status == Downloads.STATUS_CANCELED) {
+ if (mInfo.mStatus == Downloads.STATUS_CANCELED) {
if (Constants.LOGV) {
- Log.d(Constants.TAG, "canceled " + mInfo.uri);
+ Log.d(Constants.TAG, "canceled " + mInfo.mUri);
} else if (Config.LOGD) {
- // Log.d(Constants.TAG, "canceled id " + mInfo.id);
+ // Log.d(Constants.TAG, "canceled id " + mInfo.mId);
}
finalStatus = Downloads.STATUS_CANCELED;
break http_request_loop;
}
}
if (Constants.LOGV) {
- Log.v(Constants.TAG, "download completed for " + mInfo.uri);
+ Log.v(Constants.TAG, "download completed for " + mInfo.mUri);
}
finalStatus = Downloads.STATUS_SUCCESS;
}
@@ -599,16 +619,16 @@ http_request_loop:
}
finalStatus = Downloads.STATUS_FILE_ERROR;
// falls through to the code that reports an error
- } catch (Exception ex) { //sometimes the socket code throws unchecked exceptions
+ } catch (RuntimeException ex) { //sometimes the socket code throws unchecked exceptions
if (Constants.LOGV) {
- Log.d(Constants.TAG, "Exception for " + mInfo.uri, ex);
+ Log.d(Constants.TAG, "Exception for " + mInfo.mUri, ex);
} else if (Config.LOGD) {
- Log.d(Constants.TAG, "Exception for id " + mInfo.id, ex);
+ Log.d(Constants.TAG, "Exception for id " + mInfo.mId, ex);
}
finalStatus = Downloads.STATUS_UNKNOWN_ERROR;
// falls through to the code that reports an error
} finally {
- mInfo.hasActiveThread = false;
+ mInfo.mHasActiveThread = false;
if (wakeLock != null) {
wakeLock.release();
wakeLock = null;
@@ -651,6 +671,19 @@ http_request_loop:
} else if (Downloads.isStatusSuccess(finalStatus)) {
// make sure the file is readable
FileUtils.setPermissions(filename, 0644, -1, -1);
+
+ // Sync to storage after completion
+ try {
+ new FileOutputStream(filename, true).getFD().sync();
+ } catch (FileNotFoundException ex) {
+ Log.w(Constants.TAG, "file " + filename + " not found: " + ex);
+ } catch (SyncFailedException ex) {
+ Log.w(Constants.TAG, "file " + filename + " sync failed: " + ex);
+ } catch (IOException ex) {
+ Log.w(Constants.TAG, "IOException trying to sync " + filename + ": " + ex);
+ } catch (RuntimeException ex) {
+ Log.w(Constants.TAG, "exception while syncing file: ", ex);
+ }
}
}
notifyDownloadCompleted(finalStatus, countRetry, retryAfter, redirectCount,
@@ -675,24 +708,24 @@ http_request_loop:
int status, boolean countRetry, int retryAfter, int redirectCount, boolean gotData,
String filename, String uri, String mimeType) {
ContentValues values = new ContentValues();
- values.put(Downloads.STATUS, status);
+ values.put(Downloads.COLUMN_STATUS, status);
values.put(Downloads._DATA, filename);
if (uri != null) {
- values.put(Downloads.URI, uri);
+ values.put(Downloads.COLUMN_URI, uri);
}
- values.put(Downloads.MIMETYPE, mimeType);
- values.put(Downloads.LAST_MODIFICATION, System.currentTimeMillis());
- values.put(Constants.RETRY_AFTER___REDIRECT_COUNT, retryAfter + (redirectCount << 28));
+ values.put(Downloads.COLUMN_MIME_TYPE, mimeType);
+ values.put(Downloads.COLUMN_LAST_MODIFICATION, System.currentTimeMillis());
+ values.put(Constants.RETRY_AFTER_X_REDIRECT_COUNT, retryAfter + (redirectCount << 28));
if (!countRetry) {
values.put(Constants.FAILED_CONNECTIONS, 0);
} else if (gotData) {
values.put(Constants.FAILED_CONNECTIONS, 1);
} else {
- values.put(Constants.FAILED_CONNECTIONS, mInfo.numFailed + 1);
+ values.put(Constants.FAILED_CONNECTIONS, mInfo.mNumFailed + 1);
}
mContext.getContentResolver().update(
- ContentUris.withAppendedId(Downloads.CONTENT_URI, mInfo.id), values, null, null);
+ ContentUris.withAppendedId(Downloads.CONTENT_URI, mInfo.mId), values, null, null);
}
/**
@@ -700,7 +733,7 @@ http_request_loop:
* download completed even if it's not actively watching the cursor.
*/
private void notifyThroughIntent() {
- Uri uri = Uri.parse(Downloads.CONTENT_URI + "/" + mInfo.id);
+ Uri uri = Uri.parse(Downloads.CONTENT_URI + "/" + mInfo.mId);
mInfo.sendIntentIfRequested(uri, mContext);
}