summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads/DownloadThread.java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2013-02-11 16:19:39 -0800
committerJeff Sharkey <jsharkey@android.com>2013-02-12 20:24:16 -0800
commit925976230936a5177365dc24b50da8607a9af8d4 (patch)
tree0266d0edd90fbdb967f5450dfba5677da6fa2a9a /src/com/android/providers/downloads/DownloadThread.java
parent1ad10ce731d1b54692d7d5ee32601e965f503fa4 (diff)
downloadandroid_packages_providers_DownloadProvider-925976230936a5177365dc24b50da8607a9af8d4.tar.gz
android_packages_providers_DownloadProvider-925976230936a5177365dc24b50da8607a9af8d4.tar.bz2
android_packages_providers_DownloadProvider-925976230936a5177365dc24b50da8607a9af8d4.zip
Redesign of DownloadManager update loop.
Previously, the service lifecycle was managed through a large for() loop which was extremely tricky to reason about. This resulted in several race conditions that could leave the service running indefinitely, or terminate it early before tasks had finished. This change redesigns the update loop to be event driven based on database updates, and to collapse mutiple pending update passes. It is much easier to reason about service termination conditions, and it correctly uses startId to handle races during command delivery. Also moves scanner into isolated class, and switches to using public API instead of binding to private interface. Bug: 7638470, 7455406, 7162341 Change-Id: I380e77f5432223b2acb4e819e37f29f98ee4782b
Diffstat (limited to 'src/com/android/providers/downloads/DownloadThread.java')
-rw-r--r--src/com/android/providers/downloads/DownloadThread.java26
1 files changed, 22 insertions, 4 deletions
diff --git a/src/com/android/providers/downloads/DownloadThread.java b/src/com/android/providers/downloads/DownloadThread.java
index 0d427fdd..c60b02a0 100644
--- a/src/com/android/providers/downloads/DownloadThread.java
+++ b/src/com/android/providers/downloads/DownloadThread.java
@@ -20,7 +20,9 @@ import static android.provider.Downloads.Impl.STATUS_BAD_REQUEST;
import static android.provider.Downloads.Impl.STATUS_CANNOT_RESUME;
import static android.provider.Downloads.Impl.STATUS_FILE_ERROR;
import static android.provider.Downloads.Impl.STATUS_HTTP_DATA_ERROR;
+import static android.provider.Downloads.Impl.STATUS_QUEUED_FOR_WIFI;
import static android.provider.Downloads.Impl.STATUS_TOO_MANY_REDIRECTS;
+import static android.provider.Downloads.Impl.STATUS_WAITING_FOR_NETWORK;
import static android.provider.Downloads.Impl.STATUS_WAITING_TO_RETRY;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static com.android.providers.downloads.Constants.TAG;
@@ -29,7 +31,6 @@ import static java.net.HttpURLConnection.HTTP_MOVED_PERM;
import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
import static java.net.HttpURLConnection.HTTP_OK;
import static java.net.HttpURLConnection.HTTP_PARTIAL;
-import static java.net.HttpURLConnection.HTTP_PRECON_FAILED;
import static java.net.HttpURLConnection.HTTP_SEE_OTHER;
import static java.net.HttpURLConnection.HTTP_UNAVAILABLE;
@@ -218,11 +219,13 @@ public class DownloadThread implements Runnable {
}
finalStatus = error.getFinalStatus();
+ // Nobody below our level should request retries, since we handle
+ // failure counts at this level.
if (finalStatus == STATUS_WAITING_TO_RETRY) {
throw new IllegalStateException("Execution should always throw final error codes");
}
- // Some errors should be retryable later, unless we fail too many times.
+ // Some errors should be retryable, unless we fail too many times.
if (isStatusRetryable(finalStatus)) {
if (state.mGotData) {
numFailed = 1;
@@ -231,7 +234,7 @@ public class DownloadThread implements Runnable {
}
if (numFailed < Constants.MAX_RETRIES) {
- finalStatus = STATUS_WAITING_TO_RETRY;
+ finalStatus = getFinalRetryStatus();
}
}
@@ -428,6 +431,21 @@ public class DownloadThread implements Runnable {
}
/**
+ * Return retry status appropriate for current network conditions.
+ */
+ private int getFinalRetryStatus() {
+ switch (mInfo.checkCanUseNetwork()) {
+ case OK:
+ return STATUS_WAITING_TO_RETRY;
+ case UNUSABLE_DUE_TO_SIZE:
+ case RECOMMENDED_UNUSABLE_DUE_TO_SIZE:
+ return STATUS_QUEUED_FOR_WIFI;
+ default:
+ return STATUS_WAITING_FOR_NETWORK;
+ }
+ }
+
+ /**
* Transfer as much data as possible from the HTTP response to the
* destination file.
*/
@@ -805,10 +823,10 @@ public class DownloadThread implements Runnable {
*/
private void notifyDownloadCompleted(
State state, int finalStatus, String errorMsg, int numFailed) {
- notifyThroughDatabase(state, finalStatus, errorMsg, numFailed);
if (Downloads.Impl.isStatusCompleted(finalStatus)) {
mInfo.sendIntentIfRequested();
}
+ notifyThroughDatabase(state, finalStatus, errorMsg, numFailed);
}
private void notifyThroughDatabase(