Posting downloaders on executor

This commit is contained in:
ByteHamster 2019-10-30 18:05:18 +01:00
parent fe17f1bcb5
commit 366e60990d
3 changed files with 78 additions and 67 deletions

View File

@ -28,6 +28,7 @@ import de.danoeh.antennapod.core.service.GpodnetSyncService;
import de.danoeh.antennapod.core.service.download.handler.FailedDownloadHandler; import de.danoeh.antennapod.core.service.download.handler.FailedDownloadHandler;
import de.danoeh.antennapod.core.service.download.handler.FeedSyncTask; import de.danoeh.antennapod.core.service.download.handler.FeedSyncTask;
import de.danoeh.antennapod.core.service.download.handler.MediaDownloadedHandler; import de.danoeh.antennapod.core.service.download.handler.MediaDownloadedHandler;
import de.danoeh.antennapod.core.service.download.handler.PostDownloaderTask;
import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DBWriter;
@ -82,23 +83,21 @@ public class DownloadService extends Service {
*/ */
public static final String EXTRA_REQUEST = "request"; public static final String EXTRA_REQUEST = "request";
public static final int NOTIFICATION_ID = 2;
/** /**
* Contains all completed downloads that have not been included in the report yet. * Contains all completed downloads that have not been included in the report yet.
*/ */
private List<DownloadStatus> reportQueue; private final List<DownloadStatus> reportQueue;
private final ExecutorService syncExecutor;
private ExecutorService syncExecutor; private final CompletionService<Downloader> downloadExecutor;
private CompletionService<Downloader> downloadExecutor; private final DownloadRequester requester;
private final DownloadServiceNotification notificationManager;
private DownloadRequester requester;
private DownloadServiceNotification notificationManager;
public static final int NOTIFICATION_ID = 2;
/** /**
* Currently running downloads. * Currently running downloads.
*/ */
private List<Downloader> downloads; private final List<Downloader> downloads;
/** /**
* Number of running downloads. * Number of running downloads.
@ -114,11 +113,10 @@ public class DownloadService extends Service {
private NotificationUpdater notificationUpdater; private NotificationUpdater notificationUpdater;
private ScheduledFuture<?> notificationUpdaterFuture; private ScheduledFuture<?> notificationUpdaterFuture;
private ScheduledFuture<?> downloadPostFuture;
private static final int SCHED_EX_POOL_SIZE = 1; private static final int SCHED_EX_POOL_SIZE = 1;
private ScheduledThreadPoolExecutor schedExecutor; private ScheduledThreadPoolExecutor schedExecutor;
private final Handler postHandler = new Handler();
private final IBinder mBinder = new LocalBinder(); private final IBinder mBinder = new LocalBinder();
private class LocalBinder extends Binder { private class LocalBinder extends Binder {
@ -243,29 +241,13 @@ public class DownloadService extends Service {
} }
} }
@Override public DownloadService() {
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getParcelableExtra(EXTRA_REQUEST) != null) {
onDownloadQueued(intent);
} else if (numberOfDownloads.get() == 0) {
stopSelf();
}
return Service.START_NOT_STICKY;
}
@Override
public void onCreate() {
Log.d(TAG, "Service started");
isRunning = true;
handler = new Handler();
reportQueue = Collections.synchronizedList(new ArrayList<>()); reportQueue = Collections.synchronizedList(new ArrayList<>());
downloads = Collections.synchronizedList(new ArrayList<>()); downloads = Collections.synchronizedList(new ArrayList<>());
numberOfDownloads = new AtomicInteger(0); numberOfDownloads = new AtomicInteger(0);
requester = DownloadRequester.getInstance();
notificationManager = new DownloadServiceNotification(this);
IntentFilter cancelDownloadReceiverFilter = new IntentFilter();
cancelDownloadReceiverFilter.addAction(ACTION_CANCEL_ALL_DOWNLOADS);
cancelDownloadReceiverFilter.addAction(ACTION_CANCEL_DOWNLOAD);
registerReceiver(cancelDownloadReceiver, cancelDownloadReceiverFilter);
syncExecutor = Executors.newSingleThreadExecutor(r -> { syncExecutor = Executors.newSingleThreadExecutor(r -> {
Thread t = new Thread(r); Thread t = new Thread(r);
t.setPriority(Thread.MIN_PRIORITY); t.setPriority(Thread.MIN_PRIORITY);
@ -288,9 +270,31 @@ public class DownloadService extends Service {
return t; return t;
}, (r, executor) -> Log.w(TAG, "SchedEx rejected submission of new task") }, (r, executor) -> Log.w(TAG, "SchedEx rejected submission of new task")
); );
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getParcelableExtra(EXTRA_REQUEST) != null) {
onDownloadQueued(intent);
} else if (numberOfDownloads.get() == 0) {
stopSelf();
}
return Service.START_NOT_STICKY;
}
@Override
public void onCreate() {
Log.d(TAG, "Service started");
isRunning = true;
handler = new Handler();
IntentFilter cancelDownloadReceiverFilter = new IntentFilter();
cancelDownloadReceiverFilter.addAction(ACTION_CANCEL_ALL_DOWNLOADS);
cancelDownloadReceiverFilter.addAction(ACTION_CANCEL_DOWNLOAD);
registerReceiver(cancelDownloadReceiver, cancelDownloadReceiverFilter);
downloadCompletionThread.start(); downloadCompletionThread.start();
requester = DownloadRequester.getInstance();
notificationManager = new DownloadServiceNotification(this);
Notification notification = notificationManager.updateNotifications( Notification notification = notificationManager.updateNotifications(
requester.getNumberOfDownloads(), downloads); requester.getNumberOfDownloads(), downloads);
startForeground(NOTIFICATION_ID, notification); startForeground(NOTIFICATION_ID, notification);
@ -312,7 +316,6 @@ public class DownloadService extends Service {
reportQueue.clear(); reportQueue.clear();
} }
postHandler.removeCallbacks(postDownloaderTask);
EventBus.getDefault().postSticky(DownloadEvent.refresh(Collections.emptyList())); EventBus.getDefault().postSticky(DownloadEvent.refresh(Collections.emptyList()));
stopForeground(true); stopForeground(true);
@ -323,6 +326,7 @@ public class DownloadService extends Service {
syncExecutor.shutdown(); syncExecutor.shutdown();
schedExecutor.shutdown(); schedExecutor.shutdown();
cancelNotificationUpdater(); cancelNotificationUpdater();
downloadPostFuture.cancel(true);
unregisterReceiver(cancelDownloadReceiver); unregisterReceiver(cancelDownloadReceiver);
// if this was the initial gpodder sync, i.e. we just synced the feeds successfully, // if this was the initial gpodder sync, i.e. we just synced the feeds successfully,
@ -566,42 +570,20 @@ public class DownloadService extends Service {
private class NotificationUpdater implements Runnable { private class NotificationUpdater implements Runnable {
public void run() { public void run() {
handler.post(() -> { Notification n = notificationManager.updateNotifications(requester.getNumberOfDownloads(), downloads);
Notification n = notificationManager.updateNotifications( if (n != null) {
requester.getNumberOfDownloads(), downloads); NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (n != null) { nm.notify(NOTIFICATION_ID, n);
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); }
nm.notify(NOTIFICATION_ID, n);
}
});
} }
} }
private long lastPost = 0;
private final Runnable postDownloaderTask = new Runnable() {
@Override
public void run() {
List<Downloader> runningDownloads = new ArrayList<>();
for (Downloader downloader : downloads) {
if (!downloader.cancelled) {
runningDownloads.add(downloader);
}
}
List<Downloader> list = Collections.unmodifiableList(runningDownloads);
EventBus.getDefault().postSticky(DownloadEvent.refresh(list));
postHandler.postDelayed(postDownloaderTask, 1500);
}
};
private void postDownloaders() { private void postDownloaders() {
long now = System.currentTimeMillis(); new PostDownloaderTask(downloads).run();
if (now - lastPost >= 250) {
postHandler.removeCallbacks(postDownloaderTask); if (downloadPostFuture == null) {
postDownloaderTask.run(); downloadPostFuture = schedExecutor.scheduleAtFixedRate(
lastPost = now; new PostDownloaderTask(downloads), 1, 1, TimeUnit.SECONDS);
} }
} }
} }

View File

@ -17,7 +17,7 @@ public abstract class Downloader implements Callable<Downloader> {
private volatile boolean finished; private volatile boolean finished;
volatile boolean cancelled; public volatile boolean cancelled;
@NonNull @NonNull
final DownloadRequest request; final DownloadRequest request;

View File

@ -0,0 +1,29 @@
package de.danoeh.antennapod.core.service.download.handler;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.service.download.Downloader;
import org.greenrobot.eventbus.EventBus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PostDownloaderTask implements Runnable {
private List<Downloader> downloads;
public PostDownloaderTask(List<Downloader> downloads) {
this.downloads = downloads;
}
@Override
public void run() {
List<Downloader> runningDownloads = new ArrayList<>();
for (Downloader downloader : downloads) {
if (!downloader.cancelled) {
runningDownloads.add(downloader);
}
}
List<Downloader> list = Collections.unmodifiableList(runningDownloads);
EventBus.getDefault().postSticky(DownloadEvent.refresh(list));
}
}