summaryrefslogtreecommitdiffstats
path: root/src/com/android/providers/downloads/DownloadService.java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2014-01-30 15:01:39 -0800
committerJeff Sharkey <jsharkey@android.com>2014-02-06 10:42:46 -0800
commitdffbb9c4567e9d29d19964a83129e38dceab7055 (patch)
tree773bb59bc04f75e19e3a39acba06de574f75a385 /src/com/android/providers/downloads/DownloadService.java
parent9b731a5521f569c91aeb419d43fa098a34cf78cb (diff)
downloadandroid_packages_providers_DownloadProvider-dffbb9c4567e9d29d19964a83129e38dceab7055.tar.gz
android_packages_providers_DownloadProvider-dffbb9c4567e9d29d19964a83129e38dceab7055.tar.bz2
android_packages_providers_DownloadProvider-dffbb9c4567e9d29d19964a83129e38dceab7055.zip
Many improvements to download storage management.
Change all data transfer to occur through FileDescriptors instead of relying on local files. This paves the way for downloading directly to content:// Uris in the future. Rewrite storage management logic to preflight download when size is known. If enough space is found, immediately reserve the space with fallocate(), advising the kernel block allocator to try giving us a contiguous block regions to reduce fragmentation. When preflighting on internal storage or emulated external storage, ask PackageManager to clear private app caches to free up space. Since we fallocate() the entire file, use the database as the source of truth for resume locations, which requires that we fsync() before each database update. Store in-progress downloads in separate directories to keep the OS from deleting out from under us. Clean up filename generation logic to break ties in this new dual-directory case. Clearer enforcement of successful download preconditions around content lengths and ETags. Move all database field mutations to clearer DownloadInfoDelta object, and write back through single code path. Catch and log uncaught exceptions from DownloadThread. Tests to verify new storage behaviors. Fixed existing test to reflect correct RFC behavior. Bug: 5287571, 3213677, 12663412 Change-Id: I6bb905eca7c7d1a6bc88df3db28b65d70f660221
Diffstat (limited to 'src/com/android/providers/downloads/DownloadService.java')
-rw-r--r--src/com/android/providers/downloads/DownloadService.java39
1 files changed, 31 insertions, 8 deletions
diff --git a/src/com/android/providers/downloads/DownloadService.java b/src/com/android/providers/downloads/DownloadService.java
index 7d746cca..084a359c 100644
--- a/src/com/android/providers/downloads/DownloadService.java
+++ b/src/com/android/providers/downloads/DownloadService.java
@@ -54,7 +54,10 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -78,7 +81,6 @@ public class DownloadService extends Service {
SystemFacade mSystemFacade;
private AlarmManager mAlarmManager;
- private StorageManager mStorageManager;
/** Observer to get notified when the content observer's data changes */
private DownloadManagerContentObserver mObserver;
@@ -105,7 +107,28 @@ public class DownloadService extends Service {
// threads as needed (up to maximum) and reclaims them when finished.
final ThreadPoolExecutor executor = new ThreadPoolExecutor(
maxConcurrent, maxConcurrent, 10, TimeUnit.SECONDS,
- new LinkedBlockingQueue<Runnable>());
+ new LinkedBlockingQueue<Runnable>()) {
+ @Override
+ protected void afterExecute(Runnable r, Throwable t) {
+ super.afterExecute(r, t);
+
+ if (t == null && r instanceof Future<?>) {
+ try {
+ ((Future<?>) r).get();
+ } catch (CancellationException ce) {
+ t = ce;
+ } catch (ExecutionException ee) {
+ t = ee.getCause();
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ if (t != null) {
+ Log.w(TAG, "Uncaught exception", t);
+ }
+ }
+ };
executor.allowCoreThreadTimeOut(true);
return executor;
}
@@ -157,7 +180,6 @@ public class DownloadService extends Service {
}
mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
- mStorageManager = new StorageManager(this);
mUpdateThread = new HandlerThread(TAG + "-UpdateThread");
mUpdateThread.start();
@@ -198,9 +220,11 @@ public class DownloadService extends Service {
/**
* Enqueue an {@link #updateLocked()} pass to occur in future.
*/
- private void enqueueUpdate() {
- mUpdateHandler.removeMessages(MSG_UPDATE);
- mUpdateHandler.obtainMessage(MSG_UPDATE, mLastStartId, -1).sendToTarget();
+ public void enqueueUpdate() {
+ if (mUpdateHandler != null) {
+ mUpdateHandler.removeMessages(MSG_UPDATE);
+ mUpdateHandler.obtainMessage(MSG_UPDATE, mLastStartId, -1).sendToTarget();
+ }
}
/**
@@ -376,8 +400,7 @@ public class DownloadService extends Service {
* download if appropriate.
*/
private DownloadInfo insertDownloadLocked(DownloadInfo.Reader reader, long now) {
- final DownloadInfo info = reader.newDownloadInfo(
- this, mSystemFacade, mStorageManager, mNotifier);
+ final DownloadInfo info = reader.newDownloadInfo(this, mSystemFacade, mNotifier);
mDownloads.put(info.mId, info);
if (Constants.LOGVV) {