Commit 7b84a1ea by olly Committed by AquilesCanta

DownloadManager.getCurrentDownloads: Return list instead of array

- Allows enforcing immutability, which in a future CL will allow
  avoiding allocating a new array/list on every call.
- Also some left over doc cleanup from the DownloadState rename.

PiperOrigin-RevId: 243627352
parent 9ddd39c1
...@@ -23,6 +23,7 @@ import com.google.android.exoplayer2.scheduler.PlatformScheduler; ...@@ -23,6 +23,7 @@ import com.google.android.exoplayer2.scheduler.PlatformScheduler;
import com.google.android.exoplayer2.ui.DownloadNotificationHelper; import com.google.android.exoplayer2.ui.DownloadNotificationHelper;
import com.google.android.exoplayer2.util.NotificationUtil; import com.google.android.exoplayer2.util.NotificationUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.List;
/** A service for downloading media. */ /** A service for downloading media. */
public class DemoDownloadService extends DownloadService { public class DemoDownloadService extends DownloadService {
...@@ -61,7 +62,7 @@ public class DemoDownloadService extends DownloadService { ...@@ -61,7 +62,7 @@ public class DemoDownloadService extends DownloadService {
} }
@Override @Override
protected Notification getForegroundNotification(Download[] downloads) { protected Notification getForegroundNotification(List<Download> downloads) {
return notificationHelper.buildProgressNotification( return notificationHelper.buildProgressNotification(
R.drawable.ic_download, /* contentIntent= */ null, /* message= */ null, downloads); R.drawable.ic_download, /* contentIntent= */ null, /* message= */ null, downloads);
} }
......
...@@ -141,7 +141,7 @@ public class DownloadTracker implements DownloadManager.Listener { ...@@ -141,7 +141,7 @@ public class DownloadTracker implements DownloadManager.Listener {
downloads.put(download.action.uri, download); downloads.put(download.action.uri, download);
} }
} catch (IOException e) { } catch (IOException e) {
Log.w(TAG, "Failed to query download states", e); Log.w(TAG, "Failed to query downloads", e);
} }
} }
......
...@@ -46,6 +46,7 @@ import java.io.IOException; ...@@ -46,6 +46,7 @@ import java.io.IOException;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
...@@ -121,7 +122,7 @@ public final class DownloadManager { ...@@ -121,7 +122,7 @@ public final class DownloadManager {
// Messages posted to the main handler. // Messages posted to the main handler.
private static final int MSG_INITIALIZED = 0; private static final int MSG_INITIALIZED = 0;
private static final int MSG_PROCESSED = 1; private static final int MSG_PROCESSED = 1;
private static final int MSG_DOWNLOAD_STATE_CHANGED = 2; private static final int MSG_DOWNLOAD_CHANGED = 2;
private static final int MSG_DOWNLOAD_REMOVED = 3; private static final int MSG_DOWNLOAD_REMOVED = 3;
// Messages posted to the background handler. // Messages posted to the background handler.
...@@ -186,7 +187,7 @@ public final class DownloadManager { ...@@ -186,7 +187,7 @@ public final class DownloadManager {
* Constructs a {@link DownloadManager}. * Constructs a {@link DownloadManager}.
* *
* @param context Any context. * @param context Any context.
* @param databaseProvider Used to create a {@link DownloadIndex} which holds download states. * @param databaseProvider Provides the {@link DownloadIndex} that holds the downloads.
* @param downloaderFactory A factory for creating {@link Downloader}s. * @param downloaderFactory A factory for creating {@link Downloader}s.
*/ */
public DownloadManager( public DownloadManager(
...@@ -204,7 +205,7 @@ public final class DownloadManager { ...@@ -204,7 +205,7 @@ public final class DownloadManager {
* Constructs a {@link DownloadManager}. * Constructs a {@link DownloadManager}.
* *
* @param context Any context. * @param context Any context.
* @param databaseProvider Used to create a {@link DownloadIndex} which holds download states. * @param databaseProvider Provides the {@link DownloadIndex} that holds the downloads.
* @param downloaderFactory A factory for creating {@link Downloader}s. * @param downloaderFactory A factory for creating {@link Downloader}s.
* @param maxSimultaneousDownloads The maximum number of simultaneous downloads. * @param maxSimultaneousDownloads The maximum number of simultaneous downloads.
* @param minRetryCount The minimum number of times a download must be retried before failing. * @param minRetryCount The minimum number of times a download must be retried before failing.
...@@ -230,7 +231,7 @@ public final class DownloadManager { ...@@ -230,7 +231,7 @@ public final class DownloadManager {
* Constructs a {@link DownloadManager}. * Constructs a {@link DownloadManager}.
* *
* @param context Any context. * @param context Any context.
* @param downloadIndex The {@link DefaultDownloadIndex} which holds download states. * @param downloadIndex The {@link DefaultDownloadIndex} that holds the downloads.
* @param downloaderFactory A factory for creating {@link Downloader}s. * @param downloaderFactory A factory for creating {@link Downloader}s.
* @param maxSimultaneousDownloads The maximum number of simultaneous downloads. * @param maxSimultaneousDownloads The maximum number of simultaneous downloads.
* @param minRetryCount The minimum number of times a download must be retried before failing. * @param minRetryCount The minimum number of times a download must be retried before failing.
...@@ -342,8 +343,8 @@ public final class DownloadManager { ...@@ -342,8 +343,8 @@ public final class DownloadManager {
* not included. To query all downloads including those in terminal states, use {@link * not included. To query all downloads including those in terminal states, use {@link
* #getDownloadIndex()} instead. * #getDownloadIndex()} instead.
*/ */
public Download[] getCurrentDownloads() { public List<Download> getCurrentDownloads() {
return downloads.toArray(new Download[0]); return Collections.unmodifiableList(new ArrayList<>(downloads));
} }
/** /**
...@@ -467,7 +468,7 @@ public final class DownloadManager { ...@@ -467,7 +468,7 @@ public final class DownloadManager {
List<Download> downloads = (List<Download>) message.obj; List<Download> downloads = (List<Download>) message.obj;
onInitialized(downloads); onInitialized(downloads);
break; break;
case MSG_DOWNLOAD_STATE_CHANGED: case MSG_DOWNLOAD_CHANGED:
Download state = (Download) message.obj; Download state = (Download) message.obj;
onDownloadChanged(state); onDownloadChanged(state);
break; break;
...@@ -595,7 +596,7 @@ public final class DownloadManager { ...@@ -595,7 +596,7 @@ public final class DownloadManager {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
loadedStates.add(cursor.getDownload()); loadedStates.add(cursor.getDownload());
} }
logd("Download states are loaded."); logd("Downloads are loaded.");
} catch (Throwable e) { } catch (Throwable e) {
Log.e(TAG, "Download state loading failed.", e); Log.e(TAG, "Download state loading failed.", e);
loadedStates.clear(); loadedStates.clear();
...@@ -740,7 +741,7 @@ public final class DownloadManager { ...@@ -740,7 +741,7 @@ public final class DownloadManager {
if (downloadInternal.state == STATE_COMPLETED || downloadInternal.state == STATE_FAILED) { if (downloadInternal.state == STATE_COMPLETED || downloadInternal.state == STATE_FAILED) {
downloadInternals.remove(downloadInternal); downloadInternals.remove(downloadInternal);
} }
mainHandler.obtainMessage(MSG_DOWNLOAD_STATE_CHANGED, download).sendToTarget(); mainHandler.obtainMessage(MSG_DOWNLOAD_CHANGED, download).sendToTarget();
} }
private void onDownloadRemovedInternal(DownloadInternal downloadInternal, Download download) { private void onDownloadRemovedInternal(DownloadInternal downloadInternal, Download download) {
......
...@@ -33,6 +33,7 @@ import com.google.android.exoplayer2.util.Log; ...@@ -33,6 +33,7 @@ import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.NotificationUtil; import com.google.android.exoplayer2.util.NotificationUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
/** A {@link Service} for downloading media. */ /** A {@link Service} for downloading media. */
public abstract class DownloadService extends Service { public abstract class DownloadService extends Service {
...@@ -514,14 +515,14 @@ public abstract class DownloadService extends Service { ...@@ -514,14 +515,14 @@ public abstract class DownloadService extends Service {
* #FOREGROUND_NOTIFICATION_ID_NONE}. This method will not be called in this case, meaning it can * #FOREGROUND_NOTIFICATION_ID_NONE}. This method will not be called in this case, meaning it can
* be implemented to throw {@link UnsupportedOperationException}. * be implemented to throw {@link UnsupportedOperationException}.
* *
* @param downloads The states of all current downloads. * @param downloads The current downloads.
* @return The foreground notification to display. * @return The foreground notification to display.
*/ */
protected abstract Notification getForegroundNotification(Download[] downloads); protected abstract Notification getForegroundNotification(List<Download> downloads);
/** /**
* Invalidates the current foreground notification and causes {@link * Invalidates the current foreground notification and causes {@link
* #getForegroundNotification(Download[])} to be invoked again if the service isn't stopped. * #getForegroundNotification(List)} to be invoked again if the service isn't stopped.
*/ */
protected final void invalidateForegroundNotification() { protected final void invalidateForegroundNotification() {
if (foregroundNotificationUpdater != null && !isDestroyed) { if (foregroundNotificationUpdater != null && !isDestroyed) {
...@@ -600,7 +601,7 @@ public abstract class DownloadService extends Service { ...@@ -600,7 +601,7 @@ public abstract class DownloadService extends Service {
private final int notificationId; private final int notificationId;
private final long updateInterval; private final long updateInterval;
private final Handler handler; private final Handler handler;
private final Runnable callback; private final Runnable updateRunnable;
private boolean periodicUpdatesStarted; private boolean periodicUpdatesStarted;
private boolean notificationDisplayed; private boolean notificationDisplayed;
...@@ -609,7 +610,7 @@ public abstract class DownloadService extends Service { ...@@ -609,7 +610,7 @@ public abstract class DownloadService extends Service {
this.notificationId = notificationId; this.notificationId = notificationId;
this.updateInterval = updateInterval; this.updateInterval = updateInterval;
this.handler = new Handler(Looper.getMainLooper()); this.handler = new Handler(Looper.getMainLooper());
this.callback = this::update; this.updateRunnable = this::update;
} }
public void startPeriodicUpdates() { public void startPeriodicUpdates() {
...@@ -619,7 +620,7 @@ public abstract class DownloadService extends Service { ...@@ -619,7 +620,7 @@ public abstract class DownloadService extends Service {
public void stopPeriodicUpdates() { public void stopPeriodicUpdates() {
periodicUpdatesStarted = false; periodicUpdatesStarted = false;
handler.removeCallbacks(callback); handler.removeCallbacks(updateRunnable);
} }
public void showNotificationIfNotAlready() { public void showNotificationIfNotAlready() {
...@@ -635,12 +636,12 @@ public abstract class DownloadService extends Service { ...@@ -635,12 +636,12 @@ public abstract class DownloadService extends Service {
} }
private void update() { private void update() {
Download[] downloads = downloadManager.getCurrentDownloads(); List<Download> downloads = downloadManager.getCurrentDownloads();
startForeground(notificationId, getForegroundNotification(downloads)); startForeground(notificationId, getForegroundNotification(downloads));
notificationDisplayed = true; notificationDisplayed = true;
if (periodicUpdatesStarted) { if (periodicUpdatesStarted) {
handler.removeCallbacks(callback); handler.removeCallbacks(updateRunnable);
handler.postDelayed(callback, updateInterval); handler.postDelayed(updateRunnable, updateInterval);
} }
} }
} }
......
...@@ -33,6 +33,7 @@ import java.util.ArrayList; ...@@ -33,6 +33,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.junit.After; import org.junit.After;
...@@ -346,11 +347,13 @@ public class DownloadManagerTest { ...@@ -346,11 +347,13 @@ public class DownloadManagerTest {
TaskWrapper task3 = new DownloadRunner(uri3).postDownloadAction().postRemoveAction().getTask(); TaskWrapper task3 = new DownloadRunner(uri3).postDownloadAction().postRemoveAction().getTask();
task3.assertRemoving(); task3.assertRemoving();
Download[] downloads = downloadManager.getCurrentDownloads(); List<Download> downloads = downloadManager.getCurrentDownloads();
assertThat(downloads).hasLength(3); assertThat(downloads).hasSize(3);
String[] taskIds = {task1.taskId, task2.taskId, task3.taskId}; String[] taskIds = {task1.taskId, task2.taskId, task3.taskId};
String[] downloadIds = {downloads[0].action.id, downloads[1].action.id, downloads[2].action.id}; String[] downloadIds = {
downloads.get(0).action.id, downloads.get(1).action.id, downloads.get(2).action.id
};
assertThat(downloadIds).isEqualTo(taskIds); assertThat(downloadIds).isEqualTo(taskIds);
} }
......
...@@ -52,6 +52,7 @@ import java.io.File; ...@@ -52,6 +52,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
...@@ -141,7 +142,7 @@ public class DownloadServiceDashTest { ...@@ -141,7 +142,7 @@ public class DownloadServiceDashTest {
} }
@Override @Override
protected Notification getForegroundNotification(Download[] downloads) { protected Notification getForegroundNotification(List<Download> downloads) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
}; };
......
...@@ -24,6 +24,7 @@ import androidx.annotation.StringRes; ...@@ -24,6 +24,7 @@ import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.offline.Download; import com.google.android.exoplayer2.offline.Download;
import java.util.List;
/** Helper for creating download notifications. */ /** Helper for creating download notifications. */
public final class DownloadNotificationHelper { public final class DownloadNotificationHelper {
...@@ -44,26 +45,27 @@ public final class DownloadNotificationHelper { ...@@ -44,26 +45,27 @@ public final class DownloadNotificationHelper {
} }
/** /**
* Returns a progress notification for the given download states. * Returns a progress notification for the given downloads.
* *
* @param smallIcon A small icon for the notification. * @param smallIcon A small icon for the notification.
* @param contentIntent An optional content intent to send when the notification is clicked. * @param contentIntent An optional content intent to send when the notification is clicked.
* @param message An optional message to display on the notification. * @param message An optional message to display on the notification.
* @param downloads The download states. * @param downloads The downloads.
* @return The notification. * @return The notification.
*/ */
public Notification buildProgressNotification( public Notification buildProgressNotification(
@DrawableRes int smallIcon, @DrawableRes int smallIcon,
@Nullable PendingIntent contentIntent, @Nullable PendingIntent contentIntent,
@Nullable String message, @Nullable String message,
Download[] downloads) { List<Download> downloads) {
float totalPercentage = 0; float totalPercentage = 0;
int downloadTaskCount = 0; int downloadTaskCount = 0;
boolean allDownloadPercentagesUnknown = true; boolean allDownloadPercentagesUnknown = true;
boolean haveDownloadedBytes = false; boolean haveDownloadedBytes = false;
boolean haveDownloadTasks = false; boolean haveDownloadTasks = false;
boolean haveRemoveTasks = false; boolean haveRemoveTasks = false;
for (Download download : downloads) { for (int i = 0; i < downloads.size(); i++) {
Download download = downloads.get(i);
if (download.state == Download.STATE_REMOVING) { if (download.state == Download.STATE_REMOVING) {
haveRemoveTasks = true; haveRemoveTasks = true;
continue; continue;
......
...@@ -22,6 +22,7 @@ import androidx.annotation.DrawableRes; ...@@ -22,6 +22,7 @@ import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.offline.Download; import com.google.android.exoplayer2.offline.Download;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.List;
/** /**
* @deprecated Using this class can cause notifications to flicker on devices with {@link * @deprecated Using this class can cause notifications to flicker on devices with {@link
...@@ -33,14 +34,14 @@ public final class DownloadNotificationUtil { ...@@ -33,14 +34,14 @@ public final class DownloadNotificationUtil {
private DownloadNotificationUtil() {} private DownloadNotificationUtil() {}
/** /**
* Returns a progress notification for the given download states. * Returns a progress notification for the given downloads.
* *
* @param context A context for accessing resources. * @param context A context for accessing resources.
* @param smallIcon A small icon for the notification. * @param smallIcon A small icon for the notification.
* @param channelId The id of the notification channel to use. * @param channelId The id of the notification channel to use.
* @param contentIntent An optional content intent to send when the notification is clicked. * @param contentIntent An optional content intent to send when the notification is clicked.
* @param message An optional message to display on the notification. * @param message An optional message to display on the notification.
* @param downloads The download states. * @param downloads The downloads.
* @return The notification. * @return The notification.
*/ */
public static Notification buildProgressNotification( public static Notification buildProgressNotification(
...@@ -49,7 +50,7 @@ public final class DownloadNotificationUtil { ...@@ -49,7 +50,7 @@ public final class DownloadNotificationUtil {
String channelId, String channelId,
@Nullable PendingIntent contentIntent, @Nullable PendingIntent contentIntent,
@Nullable String message, @Nullable String message,
Download[] downloads) { List<Download> downloads) {
return new DownloadNotificationHelper(context, channelId) return new DownloadNotificationHelper(context, channelId)
.buildProgressNotification(smallIcon, contentIntent, message, downloads); .buildProgressNotification(smallIcon, contentIntent, message, downloads);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment