瀏覽代碼

Rename Downloader to TransferManager

As the Downloader architecture can support any type of
asynchronous operations so we can easily support file uploads.

Rename Downloader to TransferManager to reflect this.
This is just a rename, without upload implementation.
Upload feature shall follow in separate PRs.

Signed-off-by: Chris Narkiewicz <hello@ezaquarii.com>
Chris Narkiewicz 4 年之前
父節點
當前提交
b0053d1481

+ 24 - 24
src/androidTest/java/com/nextcloud/client/files/downloader/DownloaderConnectionTest.kt → src/androidTest/java/com/nextcloud/client/files/downloader/TransferManagerConnectionTest.kt

@@ -34,9 +34,9 @@ import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Before
 import org.junit.Test
 import org.junit.Test
 
 
-class DownloaderConnectionTest {
+class TransferManagerConnectionTest {
 
 
-    lateinit var connection: DownloaderConnection
+    lateinit var connection: TransferManagerConnection
 
 
     @MockK
     @MockK
     lateinit var context: Context
     lateinit var context: Context
@@ -48,10 +48,10 @@ class DownloaderConnectionTest {
     lateinit var secondDownloadListener: (Transfer) -> Unit
     lateinit var secondDownloadListener: (Transfer) -> Unit
 
 
     @MockK
     @MockK
-    lateinit var firstStatusListener: (Downloader.Status) -> Unit
+    lateinit var firstStatusListener: (TransferManager.Status) -> Unit
 
 
     @MockK
     @MockK
-    lateinit var secondStatusListener: (Downloader.Status) -> Unit
+    lateinit var secondStatusListener: (TransferManager.Status) -> Unit
 
 
     @MockK
     @MockK
     lateinit var binder: DownloaderService.Binder
     lateinit var binder: DownloaderService.Binder
@@ -63,7 +63,7 @@ class DownloaderConnectionTest {
     @Before
     @Before
     fun setUp() {
     fun setUp() {
         MockKAnnotations.init(this, relaxed = true)
         MockKAnnotations.init(this, relaxed = true)
-        connection = DownloaderConnection(context, user)
+        connection = TransferManagerConnection(context, user)
     }
     }
 
 
     @Test
     @Test
@@ -71,8 +71,8 @@ class DownloaderConnectionTest {
         // GIVEN
         // GIVEN
         //      not connected
         //      not connected
         //      listener is added
         //      listener is added
-        connection.registerDownloadListener(firstDownloadListener)
-        connection.registerDownloadListener(secondDownloadListener)
+        connection.registerTransferListener(firstDownloadListener)
+        connection.registerTransferListener(secondDownloadListener)
 
 
         // WHEN
         // WHEN
         //      service is bound
         //      service is bound
@@ -81,7 +81,7 @@ class DownloaderConnectionTest {
         // THEN
         // THEN
         //      all listeners are passed to the service
         //      all listeners are passed to the service
         val listeners = mutableListOf<(Transfer) -> Unit>()
         val listeners = mutableListOf<(Transfer) -> Unit>()
-        verify { binder.registerDownloadListener(capture(listeners)) }
+        verify { binder.registerTransferListener(capture(listeners)) }
         assertEquals(listOf(firstDownloadListener, secondDownloadListener), listeners)
         assertEquals(listOf(firstDownloadListener, secondDownloadListener), listeners)
     }
     }
 
 
@@ -93,11 +93,11 @@ class DownloaderConnectionTest {
 
 
         // WHEN
         // WHEN
         //      listeners are added
         //      listeners are added
-        connection.registerDownloadListener(firstDownloadListener)
+        connection.registerTransferListener(firstDownloadListener)
 
 
         // THEN
         // THEN
         //      listener is forwarded to service
         //      listener is forwarded to service
-        verify { binder.registerDownloadListener(firstDownloadListener) }
+        verify { binder.registerTransferListener(firstDownloadListener) }
     }
     }
 
 
     @Test
     @Test
@@ -106,8 +106,8 @@ class DownloaderConnectionTest {
         //      service is bound
         //      service is bound
         //      service has some listeners
         //      service has some listeners
         connection.onServiceConnected(componentName, binder)
         connection.onServiceConnected(componentName, binder)
-        connection.registerDownloadListener(firstDownloadListener)
-        connection.registerDownloadListener(secondDownloadListener)
+        connection.registerTransferListener(firstDownloadListener)
+        connection.registerTransferListener(secondDownloadListener)
 
 
         // WHEN
         // WHEN
         //      service unbound
         //      service unbound
@@ -115,8 +115,8 @@ class DownloaderConnectionTest {
 
 
         // THEN
         // THEN
         //      listeners removed from service
         //      listeners removed from service
-        verify { binder.removeDownloadListener(firstDownloadListener) }
-        verify { binder.removeDownloadListener(secondDownloadListener) }
+        verify { binder.removeTransferListener(firstDownloadListener) }
+        verify { binder.removeTransferListener(secondDownloadListener) }
     }
     }
 
 
     @Test
     @Test
@@ -125,19 +125,19 @@ class DownloaderConnectionTest {
         //      not bound
         //      not bound
         //      has listeners
         //      has listeners
         //      download is scheduled and is progressing
         //      download is scheduled and is progressing
-        connection.registerDownloadListener(firstDownloadListener)
-        connection.registerDownloadListener(secondDownloadListener)
+        connection.registerTransferListener(firstDownloadListener)
+        connection.registerTransferListener(secondDownloadListener)
 
 
         val request1 = Request(user, file)
         val request1 = Request(user, file)
-        connection.download(request1)
+        connection.enqueue(request1)
         val download1 = Transfer(request1.uuid, TransferState.RUNNING, 50, request1.file, request1)
         val download1 = Transfer(request1.uuid, TransferState.RUNNING, 50, request1.file, request1)
 
 
         val request2 = Request(user, file)
         val request2 = Request(user, file)
-        connection.download(request2)
+        connection.enqueue(request2)
         val download2 = Transfer(request2.uuid, TransferState.RUNNING, 50, request2.file, request1)
         val download2 = Transfer(request2.uuid, TransferState.RUNNING, 50, request2.file, request1)
 
 
-        every { binder.getDownload(request1.uuid) } returns download1
-        every { binder.getDownload(request2.uuid) } returns download2
+        every { binder.getTransfer(request1.uuid) } returns download1
+        every { binder.getTransfer(request2.uuid) } returns download2
 
 
         // WHEN
         // WHEN
         //      service is bound
         //      service is bound
@@ -159,7 +159,7 @@ class DownloaderConnectionTest {
         // GIVEN
         // GIVEN
         //      not bound
         //      not bound
         //      has status listeners
         //      has status listeners
-        val mockStatus: Downloader.Status = mockk()
+        val mockStatus: TransferManager.Status = mockk()
         every { binder.status } returns mockStatus
         every { binder.status } returns mockStatus
         connection.registerStatusListener(firstStatusListener)
         connection.registerStatusListener(firstStatusListener)
         connection.registerStatusListener(secondStatusListener)
         connection.registerStatusListener(secondStatusListener)
@@ -224,10 +224,10 @@ class DownloaderConnectionTest {
         //      not bound
         //      not bound
         //      some downloads requested without listener
         //      some downloads requested without listener
         val request = Request(user, file)
         val request = Request(user, file)
-        connection.download(request)
+        connection.enqueue(request)
         val download = Transfer(request.uuid, TransferState.RUNNING, 50, request.file, request)
         val download = Transfer(request.uuid, TransferState.RUNNING, 50, request.file, request)
-        connection.registerDownloadListener(firstDownloadListener)
-        every { binder.getDownload(request.uuid) } returns download
+        connection.registerTransferListener(firstDownloadListener)
+        every { binder.getTransfer(request.uuid) } returns download
 
 
         // WHEN
         // WHEN
         //      service is bound
         //      service is bound

+ 28 - 28
src/androidTest/java/com/nextcloud/client/files/downloader/DownloaderTest.kt → src/androidTest/java/com/nextcloud/client/files/downloader/TransferManagerTest.kt

@@ -41,15 +41,15 @@ import org.mockito.MockitoAnnotations
 
 
 @RunWith(Suite::class)
 @RunWith(Suite::class)
 @Suite.SuiteClasses(
 @Suite.SuiteClasses(
-    DownloaderTest.Enqueue::class,
-    DownloaderTest.TransferStatusUpdates::class
+    TransferManagerTest.Enqueue::class,
+    TransferManagerTest.TransferStatusUpdates::class
 )
 )
-class DownloaderTest {
+class TransferManagerTest {
 
 
     abstract class Base {
     abstract class Base {
 
 
         companion object {
         companion object {
-            const val MAX_DOWNLOAD_THREADS = 4
+            const val MAX_TRANSFER_THREADS = 4
         }
         }
 
 
         @MockK
         @MockK
@@ -67,7 +67,7 @@ class DownloaderTest {
          */
          */
         lateinit var downloadTaskMocks: MutableList<DownloadTask>
         lateinit var downloadTaskMocks: MutableList<DownloadTask>
         lateinit var runner: ManualAsyncRunner
         lateinit var runner: ManualAsyncRunner
-        lateinit var downloader: DownloaderImpl
+        lateinit var transferManager: TransferManagerImpl
 
 
         /**
         /**
          * Response value for all download tasks
          * Response value for all download tasks
@@ -86,10 +86,10 @@ class DownloaderTest {
             MockitoAnnotations.initMocks(this)
             MockitoAnnotations.initMocks(this)
             downloadTaskMocks = mutableListOf()
             downloadTaskMocks = mutableListOf()
             runner = ManualAsyncRunner()
             runner = ManualAsyncRunner()
-            downloader = DownloaderImpl(
+            transferManager = TransferManagerImpl(
                 runner = runner,
                 runner = runner,
                 taskFactory = mockTaskFactory,
                 taskFactory = mockTaskFactory,
-                threads = MAX_DOWNLOAD_THREADS
+                threads = MAX_TRANSFER_THREADS
             )
             )
             downloadTaskResult = true
             downloadTaskResult = true
             every { mockTaskFactory.create() } answers { createMockTask() }
             every { mockTaskFactory.create() } answers { createMockTask() }
@@ -120,11 +120,11 @@ class DownloaderTest {
             //      download is enqueued
             //      download is enqueued
             val file = OCFile("/path")
             val file = OCFile("/path")
             val request = Request(user, file)
             val request = Request(user, file)
-            downloader.download(request)
+            transferManager.enqueue(request)
 
 
             // THEN
             // THEN
             //      download is started immediately
             //      download is started immediately
-            val download = downloader.getDownload(request.uuid)
+            val download = transferManager.getTransfer(request.uuid)
             assertEquals(TransferState.RUNNING, download?.state)
             assertEquals(TransferState.RUNNING, download?.state)
         }
         }
 
 
@@ -132,11 +132,11 @@ class DownloaderTest {
         fun enqueued_downloads_are_pending_if_running_queue_is_full() {
         fun enqueued_downloads_are_pending_if_running_queue_is_full() {
             // GIVEN
             // GIVEN
             //      downloader is downloading max simultaneous files
             //      downloader is downloading max simultaneous files
-            for (i in 0 until MAX_DOWNLOAD_THREADS) {
+            for (i in 0 until MAX_TRANSFER_THREADS) {
                 val file = OCFile("/running/download/path/$i")
                 val file = OCFile("/running/download/path/$i")
                 val request = Request(user, file)
                 val request = Request(user, file)
-                downloader.download(request)
-                val runningDownload = downloader.getDownload(request.uuid)
+                transferManager.enqueue(request)
+                val runningDownload = transferManager.getTransfer(request.uuid)
                 assertEquals(runningDownload?.state, TransferState.RUNNING)
                 assertEquals(runningDownload?.state, TransferState.RUNNING)
             }
             }
 
 
@@ -144,11 +144,11 @@ class DownloaderTest {
             //      another download is enqueued
             //      another download is enqueued
             val file = OCFile("/path")
             val file = OCFile("/path")
             val request = Request(user, file)
             val request = Request(user, file)
-            downloader.download(request)
+            transferManager.enqueue(request)
 
 
             // THEN
             // THEN
             //      download is pending
             //      download is pending
-            val download = downloader.getDownload(request.uuid)
+            val download = transferManager.getTransfer(request.uuid)
             assertEquals(TransferState.PENDING, download?.state)
             assertEquals(TransferState.PENDING, download?.state)
         }
         }
     }
     }
@@ -166,8 +166,8 @@ class DownloaderTest {
             //      download is running
             //      download is running
             //      download is being observed
             //      download is being observed
             val downloadUpdates = mutableListOf<Transfer>()
             val downloadUpdates = mutableListOf<Transfer>()
-            downloader.registerDownloadListener { downloadUpdates.add(it) }
-            downloader.download(Request(user, file))
+            transferManager.registerTransferListener { downloadUpdates.add(it) }
+            transferManager.enqueue(Request(user, file))
 
 
             // WHEN
             // WHEN
             //      download task finishes successfully
             //      download task finishes successfully
@@ -185,8 +185,8 @@ class DownloaderTest {
             //      download is running
             //      download is running
             //      download is being observed
             //      download is being observed
             val downloadUpdates = mutableListOf<Transfer>()
             val downloadUpdates = mutableListOf<Transfer>()
-            downloader.registerDownloadListener { downloadUpdates.add(it) }
-            downloader.download(Request(user, file))
+            transferManager.registerTransferListener { downloadUpdates.add(it) }
+            transferManager.enqueue(Request(user, file))
 
 
             // WHEN
             // WHEN
             //      download task fails
             //      download task fails
@@ -204,8 +204,8 @@ class DownloaderTest {
             // GIVEN
             // GIVEN
             //      download is running
             //      download is running
             val downloadUpdates = mutableListOf<Transfer>()
             val downloadUpdates = mutableListOf<Transfer>()
-            downloader.registerDownloadListener { downloadUpdates.add(it) }
-            downloader.download(Request(user, file))
+            transferManager.registerTransferListener { downloadUpdates.add(it) }
+            transferManager.enqueue(Request(user, file))
 
 
             // WHEN
             // WHEN
             //      download progress updated 4 times before completion
             //      download progress updated 4 times before completion
@@ -232,13 +232,13 @@ class DownloaderTest {
         fun download_task_is_created_only_for_running_downloads() {
         fun download_task_is_created_only_for_running_downloads() {
             // WHEN
             // WHEN
             //      multiple downloads are enqueued
             //      multiple downloads are enqueued
-            for (i in 0 until MAX_DOWNLOAD_THREADS * 2) {
-                downloader.download(Request(user, file))
+            for (i in 0 until MAX_TRANSFER_THREADS * 2) {
+                transferManager.enqueue(Request(user, file))
             }
             }
 
 
             // THEN
             // THEN
             //      download task is created only for running downloads
             //      download task is created only for running downloads
-            assertEquals(MAX_DOWNLOAD_THREADS, downloadTaskMocks.size)
+            assertEquals(MAX_TRANSFER_THREADS, downloadTaskMocks.size)
         }
         }
     }
     }
 
 
@@ -253,11 +253,11 @@ class DownloaderTest {
             //      download is enqueued
             //      download is enqueued
             val file = OCFile("/path/to/file")
             val file = OCFile("/path/to/file")
             val request = Request(user, file)
             val request = Request(user, file)
-            downloader.download(request)
+            transferManager.enqueue(request)
 
 
             // THEN
             // THEN
             //      is running changes
             //      is running changes
-            assertTrue(downloader.isRunning)
+            assertTrue(transferManager.isRunning)
         }
         }
 
 
         @Test
         @Test
@@ -266,8 +266,8 @@ class DownloaderTest {
             //      a download is in progress
             //      a download is in progress
             val file = OCFile("/path/to/file")
             val file = OCFile("/path/to/file")
             val request = Request(user, file)
             val request = Request(user, file)
-            downloader.download(request)
-            assertTrue(downloader.isRunning)
+            transferManager.enqueue(request)
+            assertTrue(transferManager.isRunning)
 
 
             // WHEN
             // WHEN
             //      download is processed
             //      download is processed
@@ -275,7 +275,7 @@ class DownloaderTest {
 
 
             // THEN
             // THEN
             //      downloader is not running
             //      downloader is not running
-            assertFalse(downloader.isRunning)
+            assertFalse(transferManager.isRunning)
         }
         }
     }
     }
 }
 }

+ 2 - 2
src/main/java/com/nextcloud/client/etm/EtmViewModel.kt

@@ -35,7 +35,7 @@ import com.nextcloud.client.etm.pages.EtmBackgroundJobsFragment
 import com.nextcloud.client.etm.pages.EtmDownloaderFragment
 import com.nextcloud.client.etm.pages.EtmDownloaderFragment
 import com.nextcloud.client.etm.pages.EtmMigrations
 import com.nextcloud.client.etm.pages.EtmMigrations
 import com.nextcloud.client.etm.pages.EtmPreferencesFragment
 import com.nextcloud.client.etm.pages.EtmPreferencesFragment
-import com.nextcloud.client.files.downloader.DownloaderConnection
+import com.nextcloud.client.files.downloader.TransferManagerConnection
 import com.nextcloud.client.jobs.BackgroundJobManager
 import com.nextcloud.client.jobs.BackgroundJobManager
 import com.nextcloud.client.jobs.JobInfo
 import com.nextcloud.client.jobs.JobInfo
 import com.nextcloud.client.migrations.MigrationInfo
 import com.nextcloud.client.migrations.MigrationInfo
@@ -109,7 +109,7 @@ class EtmViewModel @Inject constructor(
             pageClass = EtmDownloaderFragment::class
             pageClass = EtmDownloaderFragment::class
         )
         )
     )
     )
-    val downloaderConnection = DownloaderConnection(context, accountManager.user)
+    val downloaderConnection = TransferManagerConnection(context, accountManager.user)
 
 
     val preferences: Map<String, String> get() {
     val preferences: Map<String, String> get() {
         return defaultPreferences.all
         return defaultPreferences.all

+ 4 - 4
src/main/java/com/nextcloud/client/etm/pages/EtmDownloaderFragment.kt

@@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView
 import com.nextcloud.client.etm.EtmBaseFragment
 import com.nextcloud.client.etm.EtmBaseFragment
 import com.nextcloud.client.files.downloader.Direction
 import com.nextcloud.client.files.downloader.Direction
 import com.nextcloud.client.files.downloader.Transfer
 import com.nextcloud.client.files.downloader.Transfer
-import com.nextcloud.client.files.downloader.Downloader
+import com.nextcloud.client.files.downloader.TransferManager
 import com.nextcloud.client.files.downloader.Request
 import com.nextcloud.client.files.downloader.Request
 import com.owncloud.android.R
 import com.owncloud.android.R
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.OCFile
@@ -51,7 +51,7 @@ class EtmDownloaderFragment : EtmBaseFragment() {
 
 
         private var downloads = listOf<Transfer>()
         private var downloads = listOf<Transfer>()
 
 
-        fun setStatus(status: Downloader.Status) {
+        fun setStatus(status: TransferManager.Status) {
             downloads = listOf(status.pending, status.running, status.completed).flatten().reversed()
             downloads = listOf(status.pending, status.running, status.completed).flatten().reversed()
             notifyDataSetChanged()
             notifyDataSetChanged()
         }
         }
@@ -130,10 +130,10 @@ class EtmDownloaderFragment : EtmBaseFragment() {
             Direction.DOWNLOAD,
             Direction.DOWNLOAD,
             true
             true
         )
         )
-        vm.downloaderConnection.download(request)
+        vm.downloaderConnection.enqueue(request)
     }
     }
 
 
-    private fun onDownloaderStatusChanged(status: Downloader.Status) {
+    private fun onDownloaderStatusChanged(status: TransferManager.Status) {
         adapter.setStatus(status)
         adapter.setStatus(status)
     }
     }
 }
 }

+ 8 - 8
src/main/java/com/nextcloud/client/files/downloader/DownloaderService.kt

@@ -56,13 +56,13 @@ class DownloaderService : Service() {
     }
     }
 
 
     /**
     /**
-     * Binder forwards [Downloader] API calls to selected instance of downloader.
+     * Binder forwards [TransferManager] API calls to selected instance of downloader.
      */
      */
     class Binder(
     class Binder(
-        downloader: DownloaderImpl,
+        downloader: TransferManagerImpl,
         service: DownloaderService
         service: DownloaderService
     ) : LocalBinder<DownloaderService>(service),
     ) : LocalBinder<DownloaderService>(service),
-        Downloader by downloader
+        TransferManager by downloader
 
 
     @Inject
     @Inject
     lateinit var notificationsManager: AppNotificationManager
     lateinit var notificationsManager: AppNotificationManager
@@ -79,7 +79,7 @@ class DownloaderService : Service() {
 
 
     val isRunning: Boolean get() = downloaders.any { it.value.isRunning }
     val isRunning: Boolean get() = downloaders.any { it.value.isRunning }
 
 
-    private val downloaders: MutableMap<String, DownloaderImpl> = mutableMapOf()
+    private val downloaders: MutableMap<String, TransferManagerImpl> = mutableMapOf()
 
 
     override fun onCreate() {
     override fun onCreate() {
         AndroidInjection.inject(this)
         AndroidInjection.inject(this)
@@ -99,7 +99,7 @@ class DownloaderService : Service() {
 
 
         val request = intent.getParcelableExtra(EXTRA_REQUEST) as Request
         val request = intent.getParcelableExtra(EXTRA_REQUEST) as Request
         val downloader = getDownloader(request.user)
         val downloader = getDownloader(request.user)
-        downloader.download(request)
+        downloader.enqueue(request)
 
 
         logger.d(TAG, "Enqueued new download: ${request.uuid} ${request.file.remotePath}")
         logger.d(TAG, "Enqueued new download: ${request.uuid} ${request.file.remotePath}")
 
 
@@ -136,7 +136,7 @@ class DownloaderService : Service() {
         logger.d(TAG, "Stopping downloader service")
         logger.d(TAG, "Stopping downloader service")
     }
     }
 
 
-    private fun getDownloader(user: User): DownloaderImpl {
+    private fun getDownloader(user: User): TransferManagerImpl {
         val existingDownloader = downloaders[user.accountName]
         val existingDownloader = downloaders[user.accountName]
         return if (existingDownloader != null) {
         return if (existingDownloader != null) {
             existingDownloader
             existingDownloader
@@ -146,8 +146,8 @@ class DownloaderService : Service() {
                 { clientFactory.create(user) },
                 { clientFactory.create(user) },
                 contentResolver
                 contentResolver
             )
             )
-            val newDownloader = DownloaderImpl(runner, downloadTaskFactory)
-            newDownloader.registerDownloadListener(this::onDownloadUpdate)
+            val newDownloader = TransferManagerImpl(runner, downloadTaskFactory)
+            newDownloader.registerTransferListener(this::onDownloadUpdate)
             downloaders[user.accountName] = newDownloader
             downloaders[user.accountName] = newDownloader
             newDownloader
             newDownloader
         }
         }

+ 5 - 6
src/main/java/com/nextcloud/client/files/downloader/Registry.kt

@@ -20,8 +20,7 @@
 package com.nextcloud.client.files.downloader
 package com.nextcloud.client.files.downloader
 
 
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.OCFile
-import java.lang.IllegalStateException
-import java.util.TreeMap
+import java.util.LinkedHashMap
 import java.util.UUID
 import java.util.UUID
 import kotlin.math.max
 import kotlin.math.max
 import kotlin.math.min
 import kotlin.math.min
@@ -46,9 +45,9 @@ internal class Registry(
     private val onTransferChanged: (Transfer) -> Unit,
     private val onTransferChanged: (Transfer) -> Unit,
     private val maxRunning: Int = 2
     private val maxRunning: Int = 2
 ) {
 ) {
-    private val pendingQueue = TreeMap<UUID, Transfer>()
-    private val runningQueue = TreeMap<UUID, Transfer>()
-    private val completedQueue = TreeMap<UUID, Transfer>()
+    private val pendingQueue = LinkedHashMap<UUID, Transfer>()
+    private val runningQueue = LinkedHashMap<UUID, Transfer>()
+    private val completedQueue = LinkedHashMap<UUID, Transfer>()
 
 
     val isRunning: Boolean get() = pendingQueue.size > 0 || runningQueue.size > 0
     val isRunning: Boolean get() = pendingQueue.size > 0 || runningQueue.size > 0
 
 
@@ -80,7 +79,7 @@ internal class Registry(
     fun startNext() {
     fun startNext() {
         val freeThreads = max(0, maxRunning - runningQueue.size)
         val freeThreads = max(0, maxRunning - runningQueue.size)
         for (i in 0 until min(freeThreads, pendingQueue.size)) {
         for (i in 0 until min(freeThreads, pendingQueue.size)) {
-            val key = pendingQueue.firstKey()
+            val key = pendingQueue.keys.first()
             val pendingTransfer = pendingQueue.remove(key) ?: throw IllegalStateException("Transfer $key not found")
             val pendingTransfer = pendingQueue.remove(key) ?: throw IllegalStateException("Transfer $key not found")
             val runningTransfer = pendingTransfer.copy(state = TransferState.RUNNING)
             val runningTransfer = pendingTransfer.copy(state = TransferState.RUNNING)
             runningQueue[key] = runningTransfer
             runningQueue[key] = runningTransfer

+ 20 - 20
src/main/java/com/nextcloud/client/files/downloader/Downloader.kt → src/main/java/com/nextcloud/client/files/downloader/TransferManager.kt

@@ -22,10 +22,10 @@ package com.nextcloud.client.files.downloader
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.OCFile
 import java.util.UUID
 import java.util.UUID
 
 
-interface Downloader {
+interface TransferManager {
 
 
     /**
     /**
-     * Snapshot of downloader status. All data is immutable and can be safely shared.
+     * Snapshot of transfer manager status. All data is immutable and can be safely shared.
      */
      */
     data class Status(
     data class Status(
         val pending: List<Transfer>,
         val pending: List<Transfer>,
@@ -38,27 +38,27 @@ interface Downloader {
     }
     }
 
 
     /**
     /**
-     * True if downloader has any pending or running downloads.
+     * True if transfer manager has any pending or running transfers.
      */
      */
     val isRunning: Boolean
     val isRunning: Boolean
 
 
     /**
     /**
-     * Status snapshot of all downloads.
+     * Status snapshot of all transfers.
      */
      */
     val status: Status
     val status: Status
 
 
     /**
     /**
-     * Register download progress listener. Registration is idempotent - listener can be registered only once.
+     * Register transfer progress listener. Registration is idempotent - listener can be registered only once.
      */
      */
-    fun registerDownloadListener(listener: (Transfer) -> Unit)
+    fun registerTransferListener(listener: (Transfer) -> Unit)
 
 
     /**
     /**
      * Removes registered listener if exists.
      * Removes registered listener if exists.
      */
      */
-    fun removeDownloadListener(listener: (Transfer) -> Unit)
+    fun removeTransferListener(listener: (Transfer) -> Unit)
 
 
     /**
     /**
-     * Register downloader status listener. Registration is idempotent - listener can be registered only once.
+     * Register transfer manager status listener. Registration is idempotent - listener can be registered only once.
      */
      */
     fun registerStatusListener(listener: (Status) -> Unit)
     fun registerStatusListener(listener: (Status) -> Unit)
 
 
@@ -68,31 +68,31 @@ interface Downloader {
     fun removeStatusListener(listener: (Status) -> Unit)
     fun removeStatusListener(listener: (Status) -> Unit)
 
 
     /**
     /**
-     * Adds download request to pending queue and returns immediately.
+     * Adds transfer request to pending queue and returns immediately.
      *
      *
-     * @param request Download request
+     * @param request Transfer request
      */
      */
-    fun download(request: Request)
+    fun enqueue(request: Request)
 
 
     /**
     /**
-     * Find download status by UUID.
+     * Find transfer status by UUID.
      *
      *
      * @param uuid Download process uuid
      * @param uuid Download process uuid
-     * @return download status or null if not found
+     * @return transfer status or null if not found
      */
      */
-    fun getDownload(uuid: UUID): Transfer?
+    fun getTransfer(uuid: UUID): Transfer?
 
 
     /**
     /**
-     * Query user's downloader for a download status. It performs linear search
-     * of all queues and returns first download matching [OCFile.remotePath].
+     * Query user's transfer manager for a transfer status. It performs linear search
+     * of all queues and returns first transfer matching [OCFile.remotePath].
      *
      *
-     * Since there can be multiple downloads with identical file in downloader's queues,
+     * Since there can be multiple transfers with identical file in the queues,
      * order of search matters.
      * order of search matters.
      *
      *
-     * It looks for pending downloads first, then running and completed queue last.
+     * It looks for pending transfers first, then running and completed queue last.
      *
      *
      * @param file Downloaded file
      * @param file Downloaded file
-     * @return download status or null, if download does not exist
+     * @return transfer status or null, if transfer does not exist
      */
      */
-    fun getDownload(file: OCFile): Transfer?
+    fun getTransfer(file: OCFile): Transfer?
 }
 }

+ 34 - 31
src/main/java/com/nextcloud/client/files/downloader/DownloaderConnection.kt → src/main/java/com/nextcloud/client/files/downloader/TransferManagerConnection.kt

@@ -27,47 +27,50 @@ import com.nextcloud.client.core.LocalConnection
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.datamodel.OCFile
 import java.util.UUID
 import java.util.UUID
 
 
-class DownloaderConnection(context: Context, val user: User) : LocalConnection<DownloaderService>(context), Downloader {
+class TransferManagerConnection(
+    context: Context,
+    val user: User
+) : LocalConnection<DownloaderService>(context), TransferManager {
 
 
-    private var downloadListeners: MutableSet<(Transfer) -> Unit> = mutableSetOf()
-    private var statusListeners: MutableSet<(Downloader.Status) -> Unit> = mutableSetOf()
+    private var transferListeners: MutableSet<(Transfer) -> Unit> = mutableSetOf()
+    private var statusListeners: MutableSet<(TransferManager.Status) -> Unit> = mutableSetOf()
     private var binder: DownloaderService.Binder? = null
     private var binder: DownloaderService.Binder? = null
-    private val downloadsRequiringStatusRedelivery: MutableSet<UUID> = mutableSetOf()
+    private val transfersRequiringStatusRedelivery: MutableSet<UUID> = mutableSetOf()
 
 
     override val isRunning: Boolean
     override val isRunning: Boolean
         get() = binder?.isRunning ?: false
         get() = binder?.isRunning ?: false
 
 
-    override val status: Downloader.Status
-        get() = binder?.status ?: Downloader.Status.EMPTY
+    override val status: TransferManager.Status
+        get() = binder?.status ?: TransferManager.Status.EMPTY
 
 
-    override fun getDownload(uuid: UUID): Transfer? = binder?.getDownload(uuid)
+    override fun getTransfer(uuid: UUID): Transfer? = binder?.getTransfer(uuid)
 
 
-    override fun getDownload(file: OCFile): Transfer? = binder?.getDownload(file)
+    override fun getTransfer(file: OCFile): Transfer? = binder?.getTransfer(file)
 
 
-    override fun download(request: Request) {
+    override fun enqueue(request: Request) {
         val intent = DownloaderService.createDownloadIntent(context, request)
         val intent = DownloaderService.createDownloadIntent(context, request)
         context.startService(intent)
         context.startService(intent)
-        if (!isConnected && downloadListeners.size > 0) {
-            downloadsRequiringStatusRedelivery.add(request.uuid)
+        if (!isConnected && transferListeners.size > 0) {
+            transfersRequiringStatusRedelivery.add(request.uuid)
         }
         }
     }
     }
 
 
-    override fun registerDownloadListener(listener: (Transfer) -> Unit) {
-        downloadListeners.add(listener)
-        binder?.registerDownloadListener(listener)
+    override fun registerTransferListener(listener: (Transfer) -> Unit) {
+        transferListeners.add(listener)
+        binder?.registerTransferListener(listener)
     }
     }
 
 
-    override fun removeDownloadListener(listener: (Transfer) -> Unit) {
-        downloadListeners.remove(listener)
-        binder?.removeDownloadListener(listener)
+    override fun removeTransferListener(listener: (Transfer) -> Unit) {
+        transferListeners.remove(listener)
+        binder?.removeTransferListener(listener)
     }
     }
 
 
-    override fun registerStatusListener(listener: (Downloader.Status) -> Unit) {
+    override fun registerStatusListener(listener: (TransferManager.Status) -> Unit) {
         statusListeners.add(listener)
         statusListeners.add(listener)
         binder?.registerStatusListener(listener)
         binder?.registerStatusListener(listener)
     }
     }
 
 
-    override fun removeStatusListener(listener: (Downloader.Status) -> Unit) {
+    override fun removeStatusListener(listener: (TransferManager.Status) -> Unit) {
         statusListeners.remove(listener)
         statusListeners.remove(listener)
         binder?.removeStatusListener(listener)
         binder?.removeStatusListener(listener)
     }
     }
@@ -79,8 +82,8 @@ class DownloaderConnection(context: Context, val user: User) : LocalConnection<D
     override fun onBound(binder: IBinder) {
     override fun onBound(binder: IBinder) {
         super.onBound(binder)
         super.onBound(binder)
         this.binder = binder as DownloaderService.Binder
         this.binder = binder as DownloaderService.Binder
-        downloadListeners.forEach { listener ->
-            binder.registerDownloadListener(listener)
+        transferListeners.forEach { listener ->
+            binder.registerTransferListener(listener)
         }
         }
         statusListeners.forEach { listener ->
         statusListeners.forEach { listener ->
             binder.registerStatusListener(listener)
             binder.registerStatusListener(listener)
@@ -89,23 +92,23 @@ class DownloaderConnection(context: Context, val user: User) : LocalConnection<D
     }
     }
 
 
     /**
     /**
-     * Since binding and download start are both asynchronous and the order
-     * is not guaranteed, some downloads might already finish when service is bound,
+     * Since binding and transfer start are both asynchronous and the order
+     * is not guaranteed, some transfers might already finish when service is bound,
      * resulting in lost notifications.
      * resulting in lost notifications.
      *
      *
-     * Deliver all updates for pending downloads that were scheduled
-     * before service has been bound.
+     * Deliver all updates for pending transfers that were scheduled
+     * before service was bound.
      */
      */
     private fun deliverMissedUpdates() {
     private fun deliverMissedUpdates() {
-        val downloadUpdates = downloadsRequiringStatusRedelivery.mapNotNull { uuid ->
-            binder?.getDownload(uuid)
+        val transferUpdates = transfersRequiringStatusRedelivery.mapNotNull { uuid ->
+            binder?.getTransfer(uuid)
         }
         }
-        downloadListeners.forEach { listener ->
-            downloadUpdates.forEach { update ->
+        transferListeners.forEach { listener ->
+            transferUpdates.forEach { update ->
                 listener.invoke(update)
                 listener.invoke(update)
             }
             }
         }
         }
-        downloadsRequiringStatusRedelivery.clear()
+        transfersRequiringStatusRedelivery.clear()
 
 
         if (statusListeners.isNotEmpty()) {
         if (statusListeners.isNotEmpty()) {
             binder?.status?.let { status ->
             binder?.status?.let { status ->
@@ -116,7 +119,7 @@ class DownloaderConnection(context: Context, val user: User) : LocalConnection<D
 
 
     override fun onUnbind() {
     override fun onUnbind() {
         super.onUnbind()
         super.onUnbind()
-        downloadListeners.forEach { binder?.removeDownloadListener(it) }
+        transferListeners.forEach { binder?.removeTransferListener(it) }
         statusListeners.forEach { binder?.removeStatusListener(it) }
         statusListeners.forEach { binder?.removeStatusListener(it) }
     }
     }
 }
 }

+ 29 - 26
src/main/java/com/nextcloud/client/files/downloader/DownloaderImpl.kt → src/main/java/com/nextcloud/client/files/downloader/TransferManagerImpl.kt

@@ -27,21 +27,21 @@ import com.owncloud.android.datamodel.OCFile
 import java.util.UUID
 import java.util.UUID
 
 
 /**
 /**
- * Per-user file downloader.
+ * Per-user file transfer manager.
  *
  *
- * All notifications are performed on main thread. All download processes are run
+ * All notifications are performed on main thread. All transfer processes are run
  * in the background.
  * in the background.
  *
  *
  * @param runner Background task runner. It is important to provide runner that is not shared with UI code.
  * @param runner Background task runner. It is important to provide runner that is not shared with UI code.
  * @param taskFactory Download task factory
  * @param taskFactory Download task factory
- * @param threads maximum number of concurrent download processes
+ * @param threads maximum number of concurrent transfer processes
  */
  */
-@Suppress("LongParameterList") // download operations requires those resources
-class DownloaderImpl(
+@Suppress("LongParameterList") // transfer operations requires those resources
+class TransferManagerImpl(
     private val runner: AsyncRunner,
     private val runner: AsyncRunner,
     private val taskFactory: DownloadTask.Factory,
     private val taskFactory: DownloadTask.Factory,
     threads: Int = 1
     threads: Int = 1
-) : Downloader {
+) : TransferManager {
 
 
     companion object {
     companion object {
         const val PROGRESS_PERCENTAGE_MAX = 100
         const val PROGRESS_PERCENTAGE_MAX = 100
@@ -50,51 +50,54 @@ class DownloaderImpl(
     }
     }
 
 
     private val registry = Registry(
     private val registry = Registry(
-        onStartTransfer = this::onStartDownload,
-        onTransferChanged = this::onDownloadUpdate,
+        onStartTransfer = this::onStartTransfer,
+        onTransferChanged = this::onTransferUpdate,
         maxRunning = threads
         maxRunning = threads
     )
     )
-    private val downloadListeners: MutableSet<(Transfer) -> Unit> = mutableSetOf()
-    private val statusListeners: MutableSet<(Downloader.Status) -> Unit> = mutableSetOf()
+    private val transferListeners: MutableSet<(Transfer) -> Unit> = mutableSetOf()
+    private val statusListeners: MutableSet<(TransferManager.Status) -> Unit> = mutableSetOf()
 
 
     override val isRunning: Boolean get() = registry.isRunning
     override val isRunning: Boolean get() = registry.isRunning
 
 
-    override val status: Downloader.Status
-        get() = Downloader.Status(
+    override val status: TransferManager.Status
+        get() = TransferManager.Status(
             pending = registry.pending,
             pending = registry.pending,
             running = registry.running,
             running = registry.running,
             completed = registry.completed
             completed = registry.completed
         )
         )
 
 
-    override fun registerDownloadListener(listener: (Transfer) -> Unit) {
-        downloadListeners.add(listener)
+    override fun registerTransferListener(listener: (Transfer) -> Unit) {
+        transferListeners.add(listener)
     }
     }
 
 
-    override fun removeDownloadListener(listener: (Transfer) -> Unit) {
-        downloadListeners.remove(listener)
+    override fun removeTransferListener(listener: (Transfer) -> Unit) {
+        transferListeners.remove(listener)
     }
     }
 
 
-    override fun registerStatusListener(listener: (Downloader.Status) -> Unit) {
+    override fun registerStatusListener(listener: (TransferManager.Status) -> Unit) {
         statusListeners.add(listener)
         statusListeners.add(listener)
     }
     }
 
 
-    override fun removeStatusListener(listener: (Downloader.Status) -> Unit) {
+    override fun removeStatusListener(listener: (TransferManager.Status) -> Unit) {
         statusListeners.remove(listener)
         statusListeners.remove(listener)
     }
     }
 
 
-    override fun download(request: Request) {
+    override fun enqueue(request: Request) {
         registry.add(request)
         registry.add(request)
         registry.startNext()
         registry.startNext()
     }
     }
 
 
-    override fun getDownload(uuid: UUID): Transfer? = registry.getTransfer(uuid)
+    override fun getTransfer(uuid: UUID): Transfer? = registry.getTransfer(uuid)
 
 
-    override fun getDownload(file: OCFile): Transfer? = registry.getTransfer(file)
+    override fun getTransfer(file: OCFile): Transfer? = registry.getTransfer(file)
 
 
-    private fun onStartDownload(uuid: UUID, request: Request) {
-        val downloadTask = createDownloadTask(request)
+    private fun onStartTransfer(uuid: UUID, request: Request) {
+        val transferTask = when (request.type) {
+            Direction.DOWNLOAD -> createDownloadTask(request)
+            Direction.UPLOAD -> createDownloadTask(request) // plug a hole for now - uploads are not supported
+        }
         runner.postTask(
         runner.postTask(
-            task = downloadTask,
+            task = transferTask,
             onProgress = { progress: Int -> registry.progress(uuid, progress) },
             onProgress = { progress: Int -> registry.progress(uuid, progress) },
             onResult = { result -> registry.complete(uuid, result.success, result.file); registry.startNext() },
             onResult = { result -> registry.complete(uuid, result.success, result.file); registry.startNext() },
             onError = { registry.complete(uuid, false); registry.startNext() }
             onError = { registry.complete(uuid, false); registry.startNext() }
@@ -115,8 +118,8 @@ class DownloaderImpl(
         }
         }
     }
     }
 
 
-    private fun onDownloadUpdate(transfer: Transfer) {
-        downloadListeners.forEach { it.invoke(transfer) }
+    private fun onTransferUpdate(transfer: Transfer) {
+        transferListeners.forEach { it.invoke(transfer) }
         if (statusListeners.isNotEmpty()) {
         if (statusListeners.isNotEmpty()) {
             val status = this.status
             val status = this.status
             statusListeners.forEach { it.invoke(status) }
             statusListeners.forEach { it.invoke(status) }

+ 5 - 5
src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java

@@ -60,7 +60,7 @@ import com.nextcloud.client.di.Injectable;
 import com.nextcloud.client.files.downloader.Direction;
 import com.nextcloud.client.files.downloader.Direction;
 import com.nextcloud.client.files.downloader.Transfer;
 import com.nextcloud.client.files.downloader.Transfer;
 import com.nextcloud.client.files.downloader.TransferState;
 import com.nextcloud.client.files.downloader.TransferState;
-import com.nextcloud.client.files.downloader.DownloaderConnection;
+import com.nextcloud.client.files.downloader.TransferManagerConnection;
 import com.nextcloud.client.files.downloader.Request;
 import com.nextcloud.client.files.downloader.Request;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.jobs.BackgroundJobManager;
 import com.nextcloud.client.network.ClientFactory;
 import com.nextcloud.client.network.ClientFactory;
@@ -151,7 +151,7 @@ public class ContactListFragment extends FileFragment implements Injectable {
     @Inject UserAccountManager accountManager;
     @Inject UserAccountManager accountManager;
     @Inject ClientFactory clientFactory;
     @Inject ClientFactory clientFactory;
     @Inject BackgroundJobManager backgroundJobManager;
     @Inject BackgroundJobManager backgroundJobManager;
-    private DownloaderConnection fileDownloader;
+    private TransferManagerConnection fileDownloader;
 
 
     public static ContactListFragment newInstance(OCFile file, User user) {
     public static ContactListFragment newInstance(OCFile file, User user) {
         ContactListFragment frag = new ContactListFragment();
         ContactListFragment frag = new ContactListFragment();
@@ -213,12 +213,12 @@ public class ContactListFragment extends FileFragment implements Injectable {
         ocFile = getArguments().getParcelable(FILE_NAME);
         ocFile = getArguments().getParcelable(FILE_NAME);
         setFile(ocFile);
         setFile(ocFile);
         user = getArguments().getParcelable(USER);
         user = getArguments().getParcelable(USER);
-        fileDownloader = new DownloaderConnection(getActivity(), user);
-        fileDownloader.registerDownloadListener(this::onDownloadUpdate);
+        fileDownloader = new TransferManagerConnection(getActivity(), user);
+        fileDownloader.registerTransferListener(this::onDownloadUpdate);
         fileDownloader.bind();
         fileDownloader.bind();
         if (!ocFile.isDown()) {
         if (!ocFile.isDown()) {
             Request request = new Request(user, ocFile, Direction.DOWNLOAD);
             Request request = new Request(user, ocFile, Direction.DOWNLOAD);
-            fileDownloader.download(request);
+            fileDownloader.enqueue(request);
         } else {
         } else {
             loadContactsTask.execute();
             loadContactsTask.execute();
         }
         }