diff options
author | Steve Howard <showard@google.com> | 2010-07-30 11:39:28 -0700 |
---|---|---|
committer | Steve Howard <showard@google.com> | 2010-07-30 11:39:28 -0700 |
commit | 915912de0373b78de4cd7cc1f45dad760ef94243 (patch) | |
tree | 0cecd760b984442f18dd780923c8ed5b4d06e464 /src/com/android/providers/downloads/DownloadThread.java | |
parent | 7a8bf08fe936a1fdb0408dea1ec2f39b83acc5d7 (diff) | |
parent | f85aa9ef563f2fbb3c0db6c980121122a14d953f (diff) | |
download | android_packages_providers_DownloadProvider-915912de0373b78de4cd7cc1f45dad760ef94243.tar.gz android_packages_providers_DownloadProvider-915912de0373b78de4cd7cc1f45dad760ef94243.tar.bz2 android_packages_providers_DownloadProvider-915912de0373b78de4cd7cc1f45dad760ef94243.zip |
resolved conflicts for merge of f85aa9ef to gingerbread-plus-aosp
Change-Id: I0adb03f16a6f0cc648886e02c79ffde63e18f99f
Diffstat (limited to 'src/com/android/providers/downloads/DownloadThread.java')
-rw-r--r-- | src/com/android/providers/downloads/DownloadThread.java | 159 |
1 files changed, 94 insertions, 65 deletions
diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java index d79e026d..441d48f0 100644 --- a/src/com/android/providers/downloads/DownloadThread.java +++ b/src/com/android/providers/downloads/DownloadThread.java @@ -91,16 +91,18 @@ public class DownloadThread extends Thread { public String mNewUri; public Uri mContentUri; public boolean mGotData = false; + public String mRequestUri; public State(DownloadInfo info) { mMimeType = sanitizeMimeType(info.mMimeType); mRedirectCount = info.mRedirectCount; mContentUri = Uri.parse(Downloads.Impl.CONTENT_URI + "/" + info.mId); + mRequestUri = info.mUri; } } /** - * State within the outer try block of the run() method. + * State within executeDownload() */ private static class InnerState { public int mBytesSoFar = 0; @@ -120,6 +122,12 @@ public class DownloadThread extends Thread { private class StopRequest extends Exception {} /** + * Raised from methods called by executeDownload() to indicate that the download should be + * retried immediately. + */ + private class RetryDownload extends Exception {} + + /** * Executes the download in a separate thread */ public void run() { @@ -128,12 +136,8 @@ public class DownloadThread extends Thread { State state = new State(mInfo); AndroidHttpClient client = null; PowerManager.WakeLock wakeLock = null; - HttpGet request = null; try { - InnerState innerState = new InnerState(); - byte data[] = new byte[Constants.BUFFER_SIZE]; - PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG); wakeLock.acquire(); @@ -142,40 +146,33 @@ public class DownloadThread extends Thread { if (Constants.LOGV) { Log.v(Constants.TAG, "initiating download for " + mInfo.mUri); } - setupDestinationFile(state, innerState); - client = AndroidHttpClient.newInstance(userAgent(), mContext); - // Set or unset proxy, which may have changed since last GET request. - // setDefaultProxy() supports null as proxy parameter. - ConnRouteParams.setDefaultProxy(client.getParams(), - Proxy.getPreferredHttpHost(mContext, mInfo.mUri)); - request = new HttpGet(mInfo.mUri); - addRequestHeaders(innerState, request); - - // check connectivity just before sending - if (!mInfo.canUseNetwork()) { - state.mFinalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; - return; - } - HttpResponse response = sendRequest(state, client, request); - handleExceptionalStatus(state, innerState, response); + client = AndroidHttpClient.newInstance(userAgent(), mContext); - if (Constants.LOGV) { - Log.v(Constants.TAG, "received response for " + mInfo.mUri); + boolean finished = false; + while(!finished) { + // Set or unset proxy, which may have changed since last GET request. + // setDefaultProxy() supports null as proxy parameter. + ConnRouteParams.setDefaultProxy(client.getParams(), + Proxy.getPreferredHttpHost(mContext, state.mRequestUri)); + HttpGet request = new HttpGet(state.mRequestUri); + try { + executeDownload(state, client, request); + finished = true; + } catch (RetryDownload exc) { + // fall through + } finally { + request.abort(); + request = null; + } } - processResponseHeaders(state, innerState, response); - InputStream entityStream = openResponseEntity(state, response); - transferData(state, innerState, data, entityStream); - if (Constants.LOGV) { Log.v(Constants.TAG, "download completed for " + mInfo.mUri); } state.mFinalStatus = Downloads.Impl.STATUS_SUCCESS; } catch (StopRequest error) { - if (request != null) { - request.abort(); - } + // fall through to finally block } catch (FileNotFoundException ex) { Log.d(Constants.TAG, "FileNotFoundException for " + state.mFilename + " : " + ex); state.mFinalStatus = Downloads.Impl.STATUS_FILE_ERROR; @@ -207,6 +204,43 @@ public class DownloadThread extends Thread { } /** + * Fully execute a single download request - setup and send the request, handle the response, + * and transfer the data to the destination file. + */ + private void executeDownload(State state, AndroidHttpClient client, HttpGet request) + throws StopRequest, RetryDownload, FileNotFoundException { + InnerState innerState = new InnerState(); + byte data[] = new byte[Constants.BUFFER_SIZE]; + + setupDestinationFile(state, innerState); + addRequestHeaders(innerState, request); + + // check just before sending the request to avoid using an invalid connection at all + checkConnectivity(state); + + HttpResponse response = sendRequest(state, client, request); + handleExceptionalStatus(state, innerState, response); + + if (Constants.LOGV) { + Log.v(Constants.TAG, "received response for " + mInfo.mUri); + } + + processResponseHeaders(state, innerState, response); + InputStream entityStream = openResponseEntity(state, response); + transferData(state, innerState, data, entityStream); + } + + /** + * Check if current connectivity is valid for this request. + */ + private void checkConnectivity(State state) throws StopRequest { + if (!mInfo.canUseNetwork()) { + state.mFinalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; + throw new StopRequest(); + } + } + + /** * Transfer as much data as possible from the HTTP response to the destination file. * @param data buffer to use to read data * @param entityStream stream for reading the HTTP response entity @@ -555,12 +589,8 @@ public class DownloadThread extends Thread { } updateDatabaseFromHeaders(state, innerState); - // check connectivity again now that we know the total size - if (!mInfo.canUseNetwork()) { - state.mFinalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; - throw new StopRequest(); - } + checkConnectivity(state); } /** @@ -645,7 +675,7 @@ public class DownloadThread extends Thread { * Check the HTTP response status and handle anything unusual (e.g. not 200/206). */ private void handleExceptionalStatus(State state, InnerState innerState, HttpResponse response) - throws StopRequest { + throws StopRequest, RetryDownload { int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == 503 && mInfo.mNumFailed < Constants.MAX_RETRIES) { handleServiceUnavailable(state, response); @@ -687,7 +717,7 @@ public class DownloadThread extends Thread { * Handle a 3xx redirect status. */ private void handleRedirect(State state, HttpResponse response, int statusCode) - throws StopRequest { + throws StopRequest, RetryDownload { if (Constants.LOGVV) { Log.v(Constants.TAG, "got HTTP redirect " + statusCode); } @@ -702,33 +732,35 @@ public class DownloadThread extends Thread { throw new StopRequest(); } Header header = response.getFirstHeader("Location"); - if (header != null) { - if (Constants.LOGVV) { - Log.v(Constants.TAG, "Location :" + header.getValue()); - } - try { - state.mNewUri = 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); - } - state.mFinalStatus = Downloads.Impl.STATUS_BAD_REQUEST; - throw new StopRequest(); + if (header == null) { + return; + } + if (Constants.LOGVV) { + Log.v(Constants.TAG, "Location :" + header.getValue()); + } + + String newUri; + 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); } - ++state.mRedirectCount; - state.mFinalStatus = Downloads.Impl.STATUS_RUNNING_PAUSED; + state.mFinalStatus = Downloads.Impl.STATUS_BAD_REQUEST; throw new StopRequest(); } + ++state.mRedirectCount; + state.mRequestUri = newUri; + if (statusCode == 301 || statusCode == 303) { + // use the new URI for all future requests (should a retry/resume be necessary) + state.mNewUri = newUri; + } + throw new RetryDownload(); } /** @@ -831,10 +863,7 @@ public class DownloadThread extends Thread { state.mFilename = null; } else if (mInfo.mETag == null && !mInfo.mNoIntegrity) { // Tough luck, that's not a resumable download - if (Config.LOGD) { - Log.d(Constants.TAG, - "can't resume interrupted non-resumable download"); - } + Log.d(Constants.TAG, "can't resume interrupted non-resumable download"); f.delete(); state.mFinalStatus = Downloads.Impl.STATUS_PRECONDITION_FAILED; throw new StopRequest(); |