Prevent duplicate downloads in DownloadHelper
This change modifies `DownloadHelper` to check if a URL is already scheduled for download (in pending, running, or paused status) before enqueuing a new request. If a download for the same URL is found, the existing download ID is returned, avoiding redundant requests to the `DownloadManager`. Bug: 437217681 Test: atest NetworkSecurityUnitTests Flag: EXEMPT BUGFIX Change-Id: I64dd5473b4fdb23241f5e2503c65cb64db56617c
This commit is contained in:
parent
94c93cbbe4
commit
b7c4c84a37
2 changed files with 62 additions and 1 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue