diff options
author | Jeff Sharkey <jsharkey@android.com> | 2016-04-20 23:23:09 -0600 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2016-04-25 12:59:46 -0600 |
commit | 3a5f5eafb34eaa4963c801882148e8f61514a61b (patch) | |
tree | c38ae2f58cb39e4e17be37e8eec2fe040b4b6436 /src/com/android/providers/downloads/DownloadReceiver.java | |
parent | dbcd4cfe7f0fed77a77afb1c1d242a508fc5462a (diff) | |
download | android_packages_providers_DownloadProvider-3a5f5eafb34eaa4963c801882148e8f61514a61b.tar.gz android_packages_providers_DownloadProvider-3a5f5eafb34eaa4963c801882148e8f61514a61b.tar.bz2 android_packages_providers_DownloadProvider-3a5f5eafb34eaa4963c801882148e8f61514a61b.zip |
Move DownloadManager to use JobScheduler.
JobScheduler is in a much better position to coordinate tasks across
the platform to optimize battery and RAM usage. This change removes
a bunch of manual scheduling logic by representing each download as
a separate job with relevant scheduling constraints. Requested
network types, retry backoff timing, and newly added charging and
idle constraints are plumbed through as job parameters.
When a job times out, we halt the download and schedule it to resume
later. The majority of downloads should have ETag values to enable
resuming like this.
Remove local wakelocks, since the platform now acquires and blames
our jobs on the requesting app.
When an active download is pushing updates to the database, check for
both paused and cancelled state to quickly halt an ongoing download.
Shift DownloadNotifier to update directly based on a Cursor, since we
no longer have the overhead of fully-parsed DownloadInfo objects.
Unify a handful of worker threads into a single shared thread.
Remove legacy "large download" activity that was thrown in the face
of the user; the UX best-practice is to go through notification, and
update that dialog to let the user override and continue if under
the hard limit.
Bug: 28098882, 26571724
Change-Id: I33ebe59b3c2ea9c89ec526f70b1950c734abc4a7
Diffstat (limited to 'src/com/android/providers/downloads/DownloadReceiver.java')
-rw-r--r-- | src/com/android/providers/downloads/DownloadReceiver.java | 103 |
1 files changed, 45 insertions, 58 deletions
diff --git a/src/com/android/providers/downloads/DownloadReceiver.java b/src/com/android/providers/downloads/DownloadReceiver.java index 2f50dcf6..a0dc6947 100644 --- a/src/com/android/providers/downloads/DownloadReceiver.java +++ b/src/com/android/providers/downloads/DownloadReceiver.java @@ -18,7 +18,13 @@ package com.android.providers.downloads; import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED; import static android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION; + import static com.android.providers.downloads.Constants.TAG; +import static com.android.providers.downloads.Helpers.getAsyncHandler; +import static com.android.providers.downloads.Helpers.getDownloadNotifier; +import static com.android.providers.downloads.Helpers.getInt; +import static com.android.providers.downloads.Helpers.getString; +import static com.android.providers.downloads.Helpers.getSystemFacade; import android.app.DownloadManager; import android.app.NotificationManager; @@ -29,73 +35,49 @@ import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.database.Cursor; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; import android.net.Uri; -import android.os.Handler; -import android.os.HandlerThread; import android.provider.Downloads; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.widget.Toast; -import com.google.common.annotations.VisibleForTesting; - /** * Receives system broadcasts (boot, network connectivity) */ public class DownloadReceiver extends BroadcastReceiver { /** - * Intent extra included with {@link #ACTION_CANCEL} intents, indicating the IDs (as array of - * long) of the downloads that were canceled. + * Intent extra included with {@link Constants#ACTION_CANCEL} intents, + * indicating the IDs (as array of long) of the downloads that were + * canceled. */ public static final String EXTRA_CANCELED_DOWNLOAD_IDS = "com.android.providers.downloads.extra.CANCELED_DOWNLOAD_IDS"; /** - * Intent extra included with {@link #ACTION_CANCEL} intents, indicating the tag of the - * notification corresponding to the download(s) that were canceled; this notification must be - * canceled. + * Intent extra included with {@link Constants#ACTION_CANCEL} intents, + * indicating the tag of the notification corresponding to the download(s) + * that were canceled; this notification must be canceled. */ public static final String EXTRA_CANCELED_DOWNLOAD_NOTIFICATION_TAG = "com.android.providers.downloads.extra.CANCELED_DOWNLOAD_NOTIFICATION_TAG"; - private static Handler sAsyncHandler; - - static { - final HandlerThread thread = new HandlerThread("DownloadReceiver"); - thread.start(); - sAsyncHandler = new Handler(thread.getLooper()); - } - - @VisibleForTesting - SystemFacade mSystemFacade = null; - @Override public void onReceive(final Context context, final Intent intent) { - if (mSystemFacade == null) { - mSystemFacade = new RealSystemFacade(context); - } - final String action = intent.getAction(); - if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { - startService(context); - - } else if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) { - startService(context); - - } else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) { - final ConnectivityManager connManager = (ConnectivityManager) context - .getSystemService(Context.CONNECTIVITY_SERVICE); - final NetworkInfo info = connManager.getActiveNetworkInfo(); - if (info != null && info.isConnected()) { - startService(context); - } - + if (Intent.ACTION_BOOT_COMPLETED.equals(action) + || Intent.ACTION_MEDIA_MOUNTED.equals(action)) { + final PendingResult result = goAsync(); + getAsyncHandler().post(new Runnable() { + @Override + public void run() { + handleBootCompleted(context); + result.finish(); + } + }); } else if (Intent.ACTION_UID_REMOVED.equals(action)) { final PendingResult result = goAsync(); - sAsyncHandler.post(new Runnable() { + getAsyncHandler().post(new Runnable() { @Override public void run() { handleUidRemoved(context, intent); @@ -103,9 +85,6 @@ public class DownloadReceiver extends BroadcastReceiver { } }); - } else if (Constants.ACTION_RETRY.equals(action)) { - startService(context); - } else if (Constants.ACTION_OPEN.equals(action) || Constants.ACTION_LIST.equals(action) || Constants.ACTION_HIDE.equals(action)) { @@ -115,7 +94,7 @@ public class DownloadReceiver extends BroadcastReceiver { // TODO: remove this once test is refactored handleNotificationBroadcast(context, intent); } else { - sAsyncHandler.post(new Runnable() { + getAsyncHandler().post(new Runnable() { @Override public void run() { handleNotificationBroadcast(context, intent); @@ -138,6 +117,26 @@ public class DownloadReceiver extends BroadcastReceiver { } } + private void handleBootCompleted(Context context) { + // Show any relevant notifications for completed downloads + getDownloadNotifier(context).update(); + + // Schedule all downloads that are ready + final ContentResolver resolver = context.getContentResolver(); + try (Cursor cursor = resolver.query(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, null, null, + null, null)) { + final DownloadInfo.Reader reader = new DownloadInfo.Reader(resolver, cursor); + final DownloadInfo info = new DownloadInfo(context); + while (cursor.moveToNext()) { + reader.updateFromDatabase(info); + Helpers.scheduleJob(context, info); + } + } + + // Schedule idle pass to clean up orphaned files + DownloadIdleService.scheduleIdlePass(context); + } + private void handleUidRemoved(Context context, Intent intent) { final ContentResolver resolver = context.getContentResolver(); @@ -266,18 +265,6 @@ public class DownloadReceiver extends BroadcastReceiver { } } - mSystemFacade.sendBroadcast(appIntent); - } - - private static String getString(Cursor cursor, String col) { - return cursor.getString(cursor.getColumnIndexOrThrow(col)); - } - - private static int getInt(Cursor cursor, String col) { - return cursor.getInt(cursor.getColumnIndexOrThrow(col)); - } - - private void startService(Context context) { - context.startService(new Intent(context, DownloadService.class)); + getSystemFacade(context).sendBroadcast(appIntent); } } |