package de.danoeh.antennapod.core.storage;
import android.content.Context;
import android.util.Log;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import de.danoeh.antennapod.core.feed.FeedFilter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.core.util.PowerUtils;
/**
* Implements the automatic download algorithm used by AntennaPod. This class assumes that
* the client uses the APEpisodeCleanupAlgorithm.
*/
public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
private static final String TAG = "APDownloadAlgorithm";
/**
* Looks for undownloaded episodes in the queue or list of new items and request a download if
* 1. Network is available
* 2. The device is charging or the user allows auto download on battery
* 3. There is free space in the episode cache
* This method is executed on an internal single thread executor.
*
* @param context Used for accessing the DB.
* @return A Runnable that will be submitted to an ExecutorService.
*/
@Override
public Runnable autoDownloadUndownloadedItems(final Context context) {
return () -> {
// true if we should auto download based on network status
boolean networkShouldAutoDl = NetworkUtils.autodownloadNetworkAvailable()
&& UserPreferences.isEnableAutodownload();
// true if we should auto download based on power status
boolean powerShouldAutoDl = PowerUtils.deviceCharging(context)
|| UserPreferences.isEnableAutodownloadOnBattery();
// we should only auto download if both network AND power are happy
if (networkShouldAutoDl && powerShouldAutoDl) {
Log.d(TAG, "Performing auto-dl of undownloaded episodes");
List<FeedItem> candidates;
final List<FeedItem> queue = DBReader.getQueue();
final List<FeedItem> newItems = DBReader.getNewItemsList();
candidates = new ArrayList<>(queue.size() + newItems.size());
candidates.addAll(queue);
for(FeedItem newItem : newItems) {
FeedPreferences feedPrefs = newItem.getFeed().getPreferences();
FeedFilter feedFilter = feedPrefs.getFilter();
if(!candidates.contains(newItem) && feedFilter.shouldAutoDownload(newItem)) {
candidates.add(newItem);
}
}
// filter items that are not auto downloadable
Iterator<FeedItem> it = candidates.iterator();
while(it.hasNext()) {
FeedItem item = it.next();
if(!item.isAutoDownloadable()) {
it.remove();
}
}
int autoDownloadableEpisodes = candidates.size();
int downloadedEpisodes = DBReader.getNumberOfDownloadedEpisodes();
int deletedEpisodes = UserPreferences.getEpisodeCleanupAlgorithm()
.makeRoomForEpisodes(context, autoDownloadableEpisodes);
boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences
.getEpisodeCacheSizeUnlimited();
int episodeCacheSize = UserPreferences.getEpisodeCacheSize();
int episodeSpaceLeft;
if (cacheIsUnlimited ||
episodeCacheSize >= downloadedEpisodes + autoDownloadableEpisodes) {
episodeSpaceLeft = autoDownloadableEpisodes;
} else {
episodeSpaceLeft = episodeCacheSize - (downloadedEpisodes - deletedEpisodes);
}
FeedItem[] itemsToDownload = candidates.subList(0, episodeSpaceLeft)
.toArray(new FeedItem[episodeSpaceLeft]);
Log.d(TAG, "Enqueueing " + itemsToDownload.length + " items for download");
try {
DBTasks.downloadFeedItems(false, context, itemsToDownload);
} catch (DownloadRequestException e) {
e.printStackTrace();
}
}
};
}
}