From 38648831a92295e9a11831e19e5a9dab4cbd939e Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Sat, 12 Jan 2013 15:58:51 -0800 Subject: Cleaner thread management, less global state. Switch to using a ThreadPoolExecutor for handling downloads, which gives us parallelism logic that is easier to reason about. Also open the door to eventually waiting until the executor is drained to stopSelf(). Removes DownloadHandler singleton, and gives explicit path for publishing active download speeds to notifications. Change-Id: I1836e7742bb8a84861d1ca6bd1e59b2040bd12f8 --- .../providers/downloads/DownloadService.java | 30 ++++++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'src/com/android/providers/downloads/DownloadService.java') diff --git a/src/com/android/providers/downloads/DownloadService.java b/src/com/android/providers/downloads/DownloadService.java index 4a1b40d5..039f12cd 100644 --- a/src/com/android/providers/downloads/DownloadService.java +++ b/src/com/android/providers/downloads/DownloadService.java @@ -26,6 +26,7 @@ import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.content.res.Resources; import android.database.ContentObserver; import android.database.Cursor; import android.media.IMediaScannerListener; @@ -53,6 +54,10 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * Performs the background downloads requested by applications that use the Downloads provider. @@ -76,12 +81,26 @@ public class DownloadService extends Service { @GuardedBy("mDownloads") private Map mDownloads = Maps.newHashMap(); + private final ExecutorService mExecutor = buildDownloadExecutor(); + + private static ExecutorService buildDownloadExecutor() { + final int maxConcurrent = Resources.getSystem().getInteger( + com.android.internal.R.integer.config_MaxConcurrentDownloadsAllowed); + + // Create a bounded thread pool for executing downloads; it creates + // threads as needed (up to maximum) and reclaims them when finished. + final ThreadPoolExecutor executor = new ThreadPoolExecutor( + maxConcurrent, maxConcurrent, 10, TimeUnit.SECONDS, + new LinkedBlockingQueue()); + executor.allowCoreThreadTimeOut(true); + return executor; + } + /** * The thread that updates the internal download list from the content * provider. */ - @VisibleForTesting - UpdateThread mUpdateThread; + private UpdateThread mUpdateThread; /** * Whether the internal download list should be updated from the content @@ -435,14 +454,15 @@ public class DownloadService extends Service { * download if appropriate. */ private DownloadInfo insertDownloadLocked(DownloadInfo.Reader reader, long now) { - DownloadInfo info = reader.newDownloadInfo(this, mSystemFacade, mStorageManager); + final DownloadInfo info = reader.newDownloadInfo( + this, mSystemFacade, mStorageManager, mNotifier); mDownloads.put(info.mId, info); if (Constants.LOGVV) { Log.v(Constants.TAG, "processing inserted download " + info.mId); } - info.startIfReady(now, mStorageManager); + info.startIfReady(mExecutor); return info; } @@ -458,7 +478,7 @@ public class DownloadService extends Service { Log.v(Constants.TAG, "processing updated download " + info.mId + ", status: " + info.mStatus); } - info.startIfReady(now, mStorageManager); + info.startIfReady(mExecutor); } /** -- cgit v1.2.3