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
This commit is contained in:
olly 2019-04-15 17:11:03 +01:00 committed by AquilesCanta
parent 9ddd39c1c0
commit 7b84a1ead7
8 changed files with 41 additions and 31 deletions

View file

@ -23,6 +23,7 @@ import com.google.android.exoplayer2.scheduler.PlatformScheduler;
import com.google.android.exoplayer2.ui.DownloadNotificationHelper;
import com.google.android.exoplayer2.util.NotificationUtil;
import com.google.android.exoplayer2.util.Util;
import java.util.List;
/** A service for downloading media. */
public class DemoDownloadService extends DownloadService {
@ -61,7 +62,7 @@ public class DemoDownloadService extends DownloadService {
}
@Override
protected Notification getForegroundNotification(Download[] downloads) {
protected Notification getForegroundNotification(List<Download> downloads) {
return notificationHelper.buildProgressNotification(
R.drawable.ic_download, /* contentIntent= */ null, /* message= */ null, downloads);
}

View file

@ -141,7 +141,7 @@ public class DownloadTracker implements DownloadManager.Listener {
downloads.put(download.action.uri, download);
}
} catch (IOException e) {
Log.w(TAG, "Failed to query download states", e);
Log.w(TAG, "Failed to query downloads", e);
}
}

View file

@ -46,6 +46,7 @@ import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
@ -121,7 +122,7 @@ public final class DownloadManager {
// Messages posted to the main handler.
private static final int MSG_INITIALIZED = 0;
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;
// Messages posted to the background handler.
@ -186,7 +187,7 @@ public final class DownloadManager {
* Constructs a {@link DownloadManager}.
*
* @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.
*/
public DownloadManager(
@ -204,7 +205,7 @@ public final class DownloadManager {
* Constructs a {@link DownloadManager}.
*
* @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 maxSimultaneousDownloads The maximum number of simultaneous downloads.
* @param minRetryCount The minimum number of times a download must be retried before failing.
@ -230,7 +231,7 @@ public final class DownloadManager {
* Constructs a {@link DownloadManager}.
*
* @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 maxSimultaneousDownloads The maximum number of simultaneous downloads.
* @param minRetryCount The minimum number of times a download must be retried before failing.
@ -342,8 +343,8 @@ public final class DownloadManager {
* not included. To query all downloads including those in terminal states, use {@link
* #getDownloadIndex()} instead.
*/
public Download[] getCurrentDownloads() {
return downloads.toArray(new Download[0]);
public List<Download> getCurrentDownloads() {
return Collections.unmodifiableList(new ArrayList<>(downloads));
}
/**
@ -467,7 +468,7 @@ public final class DownloadManager {
List<Download> downloads = (List<Download>) message.obj;
onInitialized(downloads);
break;
case MSG_DOWNLOAD_STATE_CHANGED:
case MSG_DOWNLOAD_CHANGED:
Download state = (Download) message.obj;
onDownloadChanged(state);
break;
@ -595,7 +596,7 @@ public final class DownloadManager {
while (cursor.moveToNext()) {
loadedStates.add(cursor.getDownload());
}
logd("Download states are loaded.");
logd("Downloads are loaded.");
} catch (Throwable e) {
Log.e(TAG, "Download state loading failed.", e);
loadedStates.clear();
@ -740,7 +741,7 @@ public final class DownloadManager {
if (downloadInternal.state == STATE_COMPLETED || downloadInternal.state == STATE_FAILED) {
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) {

View file

@ -33,6 +33,7 @@ import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.NotificationUtil;
import com.google.android.exoplayer2.util.Util;
import java.util.HashMap;
import java.util.List;
/** A {@link Service} for downloading media. */
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
* 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.
*/
protected abstract Notification getForegroundNotification(Download[] downloads);
protected abstract Notification getForegroundNotification(List<Download> downloads);
/**
* 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() {
if (foregroundNotificationUpdater != null && !isDestroyed) {
@ -600,7 +601,7 @@ public abstract class DownloadService extends Service {
private final int notificationId;
private final long updateInterval;
private final Handler handler;
private final Runnable callback;
private final Runnable updateRunnable;
private boolean periodicUpdatesStarted;
private boolean notificationDisplayed;
@ -609,7 +610,7 @@ public abstract class DownloadService extends Service {
this.notificationId = notificationId;
this.updateInterval = updateInterval;
this.handler = new Handler(Looper.getMainLooper());
this.callback = this::update;
this.updateRunnable = this::update;
}
public void startPeriodicUpdates() {
@ -619,7 +620,7 @@ public abstract class DownloadService extends Service {
public void stopPeriodicUpdates() {
periodicUpdatesStarted = false;
handler.removeCallbacks(callback);
handler.removeCallbacks(updateRunnable);
}
public void showNotificationIfNotAlready() {
@ -635,12 +636,12 @@ public abstract class DownloadService extends Service {
}
private void update() {
Download[] downloads = downloadManager.getCurrentDownloads();
List<Download> downloads = downloadManager.getCurrentDownloads();
startForeground(notificationId, getForegroundNotification(downloads));
notificationDisplayed = true;
if (periodicUpdatesStarted) {
handler.removeCallbacks(callback);
handler.postDelayed(callback, updateInterval);
handler.removeCallbacks(updateRunnable);
handler.postDelayed(updateRunnable, updateInterval);
}
}
}

View file

@ -33,6 +33,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.After;
@ -346,11 +347,13 @@ public class DownloadManagerTest {
TaskWrapper task3 = new DownloadRunner(uri3).postDownloadAction().postRemoveAction().getTask();
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[] 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);
}

View file

@ -52,6 +52,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
@ -141,7 +142,7 @@ public class DownloadServiceDashTest {
}
@Override
protected Notification getForegroundNotification(Download[] downloads) {
protected Notification getForegroundNotification(List<Download> downloads) {
throw new UnsupportedOperationException();
}
};

View file

@ -24,6 +24,7 @@ import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.offline.Download;
import java.util.List;
/** Helper for creating download notifications. */
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 contentIntent An optional content intent to send when the notification is clicked.
* @param message An optional message to display on the notification.
* @param downloads The download states.
* @param downloads The downloads.
* @return The notification.
*/
public Notification buildProgressNotification(
@DrawableRes int smallIcon,
@Nullable PendingIntent contentIntent,
@Nullable String message,
Download[] downloads) {
List<Download> downloads) {
float totalPercentage = 0;
int downloadTaskCount = 0;
boolean allDownloadPercentagesUnknown = true;
boolean haveDownloadedBytes = false;
boolean haveDownloadTasks = 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) {
haveRemoveTasks = true;
continue;

View file

@ -22,6 +22,7 @@ import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.offline.Download;
import com.google.android.exoplayer2.util.Util;
import java.util.List;
/**
* @deprecated Using this class can cause notifications to flicker on devices with {@link
@ -33,14 +34,14 @@ public final class 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 smallIcon A small icon for the notification.
* @param channelId The id of the notification channel to use.
* @param contentIntent An optional content intent to send when the notification is clicked.
* @param message An optional message to display on the notification.
* @param downloads The download states.
* @param downloads The downloads.
* @return The notification.
*/
public static Notification buildProgressNotification(
@ -49,7 +50,7 @@ public final class DownloadNotificationUtil {
String channelId,
@Nullable PendingIntent contentIntent,
@Nullable String message,
Download[] downloads) {
List<Download> downloads) {
return new DownloadNotificationHelper(context, channelId)
.buildProgressNotification(smallIcon, contentIntent, message, downloads);
}