Merge "Prevent duplicate downloads in DownloadHelper" into main

This commit is contained in:
Sandro Montanari 2025-09-01 01:41:00 -07:00 • committed by Android (Google) Code Review
commit 34465d06c8
2 changed files with 62 additions and 1 deletions

View file

@ -25,6 +25,7 @@ import android.net.Uri;
import androidx.annotation.VisibleForTesting;
import com.google.auto.value.AutoValue;
import java.util.Objects;
/** Class to handle downloads for Certificate Transparency. */
public class DownloadHelper {
@ -47,6 +48,10 @@ public class DownloadHelper {
* @return a downloadId if the request was created successfully, -1 otherwise.
*/
public long startDownload(String url) {
long downloadId = isUrlAlreadyScheduled(url);
if (downloadId != -1) {
return downloadId;
}
return mDownloadManager.enqueue(
new Request(Uri.parse(url))
.setAllowedOverRoaming(false)
@ -54,6 +59,33 @@ public class DownloadHelper {
.setRequiresCharging(true));
}
private long isUrlAlreadyScheduled(String url) {
try (Cursor cursor =
mDownloadManager.query(
new Query()
.setFilterByStatus(
DownloadManager.STATUS_PENDING
| DownloadManager.STATUS_RUNNING
| DownloadManager.STATUS_PAUSED))) {
if (cursor == null) {
return -1;
}
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
int idIndex = cursor.getColumnIndex(DownloadManager.COLUMN_ID);
int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_URI);
if (idIndex == -1 || uriIndex == -1) {
continue;
}
long downloadId = cursor.getLong(idIndex);
String uri = cursor.getString(uriIndex);
if (Objects.equals(uri, url)) {
return downloadId;
}
}
}
return -1;
}
/**
* Returns the status of the provided download id.
*
@ -67,7 +99,7 @@ public class DownloadHelper {
builder.setStatus(
cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)));
builder.setReason(
cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_REASON)));
cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_REASON)));
}
}
return builder.build();

View file

@ -23,6 +23,7 @@ import static org.mockito.Mockito.when;
import android.app.DownloadManager;
import android.database.MatrixCursor;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -53,6 +54,21 @@ public class DownloadHelperTest {
assertThat(mDownloadHelper.startDownload("http://test.org")).isEqualTo(downloadId);
}
@Test
public void testDownloadHelper_multipleDownloads_doesNotRescheduleDuplicates() {
long downloadId1 = 666;
String url1 = "http://test1.org";
long downloadId2 = 777;
String url2 = "http://test2.org";
when(mDownloadManager.enqueue(any())).thenReturn(downloadId1, downloadId2);
assertThat(mDownloadHelper.startDownload(url1)).isEqualTo(downloadId1);
mockPendingDownload(downloadId1, url1);
assertThat(mDownloadHelper.startDownload(url2)).isEqualTo(downloadId2);
assertThat(mDownloadHelper.startDownload(url1)).isEqualTo(downloadId1);
}
@Test
public void testDownloadHelper_wrongUri() {
when(mDownloadManager.enqueue(any())).thenReturn(666L);
@ -60,4 +76,17 @@ public class DownloadHelperTest {
assertThrows(
IllegalArgumentException.class, () -> mDownloadHelper.startDownload("not_a_uri"));
}
private void mockPendingDownload(long downloadId, String url) {
MatrixCursor cursor =
new MatrixCursor(
new String[] {
DownloadManager.COLUMN_ID,
DownloadManager.COLUMN_URI,
DownloadManager.COLUMN_STATUS
});
cursor.addRow(new Object[] {downloadId, url, DownloadManager.STATUS_PENDING});
when(mDownloadManager.query(any())).thenReturn(cursor);
}
}