瀏覽代碼

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.Test
 
-class DownloaderConnectionTest {
+class TransferManagerConnectionTest {
 
-    lateinit var connection: DownloaderConnection
+    lateinit var connection: TransferManagerConnection
 
     @MockK
     lateinit var context: Context
@@ -48,10 +48,10 @@ class DownloaderConnectionTest {
     lateinit var secondDownloadListener: (Transfer) -> Unit
 
     @MockK
-    lateinit var firstStatusListener: (Downloader.Status) -> Unit
+    lateinit var firstStatusListener: (TransferManager.Status) -> Unit
 
     @MockK
-    lateinit var secondStatusListener: (Downloader.Status) -> Unit
+    lateinit var secondStatusListener: (TransferManager.Status) -> Unit
 
     @MockK
     lateinit var binder: DownloaderService.Binder
@@ -63,7 +63,7 @@ class DownloaderConnectionTest {
     @Before
     fun setUp() {
         MockKAnnotations.init(this, relaxed = true)
-        connection = DownloaderConnection(context, user)
+        connection = TransferManagerConnection(context, user)
     }
 
     @Test
@@ -71,8 +71,8 @@ class DownloaderConnectionTest {
         // GIVEN
         //      not connected
         //      listener is added
-        connection.registerDownloadListener(firstDownloadListener)
-        connection.registerDownloadListener(secondDownloadListener)
+        connection.registerTransferListener(firstDownloadListener)
+        connection.registerTransferListener(secondDownloadListener)
 
         // WHEN
         //      service is bound
@@ -81,7 +81,7 @@ class DownloaderConnectionTest {
         // THEN
         //      all listeners are passed to the service
         val listeners = mutableListOf<(Transfer) -> Unit>()
-        verify { binder.registerDownloadListener(capture(listeners)) }
+        verify { binder.registerTransferListener(capture(listeners)) }
         assertEquals(listOf(firstDownloadListener, secondDownloadListener), listeners)
     }
 
@@ -93,11 +93,11 @@ class DownloaderConnectionTest {
 
         // WHEN
         //      listeners are added
-        connection.registerDownloadListener(firstDownloadListener)
+        connection.registerTransferListener(firstDownloadListener)
 
         // THEN
         //      listener is forwarded to service
-        verify { binder.registerDownloadListener(firstDownloadListener) }
+        verify { binder.registerTransferListener(firstDownloadListener) }
     }
 
     @Test
@@ -106,8 +106,8 @@ class DownloaderConnectionTest {
         //      service is bound
         //      service has some listeners
         connection.onServiceConnected(componentName, binder)
-        connection.registerDownloadListener(firstDownloadListener)
-        connection.registerDownloadListener(secondDownloadListener)
+        connection.registerTransferListener(firstDownloadListener)
+        connection.registerTransferListener(secondDownloadListener)
 
         // WHEN
         //      service unbound
@@ -115,8 +115,8 @@ class DownloaderConnectionTest {
 
         // THEN
         //      listeners removed from service
-        verify { binder.removeDownloadListener(firstDownloadListener) }
-        verify { binder.removeDownloadListener(secondDownloadListener) }
+        verify { binder.removeTransferListener(firstDownloadListener) }
+        verify { binder.removeTransferListener(secondDownloadListener) }
     }
 
     @Test
@@ -125,19 +125,19 @@ class DownloaderConnectionTest {
         //      not bound
         //      has listeners
         //      download is scheduled and is progressing
-        connection.registerDownloadListener(firstDownloadListener)
-        connection.registerDownloadListener(secondDownloadListener)
+        connection.registerTransferListener(firstDownloadListener)
+        connection.registerTransferListener(secondDownloadListener)
 
         val request1 = Request(user, file)
-        connection.download(request1)
+        connection.enqueue(request1)
         val download1 = Transfer(request1.uuid, TransferState.RUNNING, 50, request1.file, request1)
 
         val request2 = Request(user, file)
-        connection.download(request2)
+        connection.enqueue(request2)
         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
         //      service is bound
@@ -159,7 +159,7 @@ class DownloaderConnectionTest {
         // GIVEN
         //      not bound
         //      has status listeners
-        val mockStatus: Downloader.Status = mockk()
+        val mockStatus: TransferManager.Status = mockk()
         every { binder.status } returns mockStatus
         connection.registerStatusListener(firstStatusListener)
         connection.registerStatusListener(secondStatusListener)
@@ -224,10 +224,10 @@ class DownloaderConnectionTest {
         //      not bound
         //      some downloads requested without listener
         val request = Request(user, file)
-        connection.download(request)
+        connection.enqueue(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
         //      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)
 @Suite.SuiteClasses(
-    DownloaderTest.Enqueue::class,
-    DownloaderTest.TransferStatusUpdates::class
+    TransferManagerTest.Enqueue::class,
+    TransferManagerTest.TransferStatusUpdates::class
 )
-class DownloaderTest {
+class TransferManagerTest {
 
     abstract class Base {
 
         companion object {
-            const val MAX_DOWNLOAD_THREADS = 4
+            const val MAX_TRANSFER_THREADS = 4
         }
 
         @MockK
@@ -67,7 +67,7 @@ class DownloaderTest {
          */
         lateinit var downloadTaskMocks: MutableList<DownloadTask>
         lateinit var runner: ManualAsyncRunner
-        lateinit var downloader: DownloaderImpl
+        lateinit var transferManager: TransferManagerImpl
 
         /**
          * Response value for all download tasks
@@ -86,10 +86,10 @@ class DownloaderTest {
             MockitoAnnotations.initMocks(this)
             downloadTaskMocks = mutableListOf()
             runner = ManualAsyncRunner()
-            downloader = DownloaderImpl(
+            transferManager = TransferManagerImpl(
                 runner = runner,
                 taskFactory = mockTaskFactory,
-                threads = MAX_DOWNLOAD_THREADS
+                threads = MAX_TRANSFER_THREADS
             )
             downloadTaskResult = true
             every { mockTaskFactory.create() } answers { createMockTask() }
@@ -120,11 +120,11 @@ class DownloaderTest {
             //      download is enqueued
             val file = OCFile("/path")
             val request = Request(user, file)
-            downloader.download(request)
+            transferManager.enqueue(request)
 
             // THEN
             //      download is started immediately
-            val download = downloader.getDownload(request.uuid)
+            val download = transferManager.getTransfer(request.uuid)
             assertEquals(TransferState.RUNNING, download?.state)
         }
 
@@ -132,11 +132,11 @@ class DownloaderTest {
         fun enqueued_downloads_are_pending_if_running_queue_is_full() {
             // GIVEN
             //      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 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)
             }
 
@@ -144,11 +144,11 @@ class DownloaderTest {
             //      another download is enqueued
             val file = OCFile("/path")
             val request = Request(user, file)
-            downloader.download(request)
+            transferManager.enqueue(request)
 
             // THEN
             //      download is pending
-            val download = downloader.getDownload(request.uuid)
+            val download = transferManager.getTransfer(request.uuid)
             assertEquals(TransferState.PENDING, download?.state)
         }
     }
@@ -166,8 +166,8 @@ class DownloaderTest {
             //      download is running
             //      download is being observed
             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
             //      download task finishes successfully
@@ -185,8 +185,8 @@ class DownloaderTest {
             //      download is running
             //      download is being observed
             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
             //      download task fails
@@ -204,8 +204,8 @@ class DownloaderTest {
             // GIVEN
             //      download is running
             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
             //      download progress updated 4 times before completion
@@ -232,13 +232,13 @@ class DownloaderTest {
         fun download_task_is_created_only_for_running_downloads() {
             // WHEN
             //      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
             //      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
             val file = OCFile("/path/to/file")
             val request = Request(user, file)
-            downloader.download(request)
+            transferManager.enqueue(request)
 
             // THEN
             //      is running changes
-            assertTrue(downloader.isRunning)
+            assertTrue(transferManager.isRunning)
         }
 
         @Test
@@ -266,8 +266,8 @@ class DownloaderTest {
             //      a download is in progress
             val file = OCFile("/path/to/file")
             val request = Request(user, file)
-            downloader.download(request)
-            assertTrue(downloader.isRunning)
+            transferManager.enqueue(request)
+            assertTrue(transferManager.isRunning)
 
             // WHEN
             //      download is processed
@@ -275,7 +275,7 @@ class DownloaderTest {
 
             // THEN
             //      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.EtmMigrations
 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.JobInfo
 import com.nextcloud.client.migrations.MigrationInfo
@@ -109,7 +109,7 @@ class EtmViewModel @Inject constructor(
             pageClass = EtmDownloaderFragment::class
         )
     )
-    val downloaderConnection = DownloaderConnection(context, accountManager.user)
+    val downloaderConnection = TransferManagerConnection(context, accountManager.user)
 
     val preferences: Map<String, String> get() {
         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.files.downloader.Direction
 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.owncloud.android.R
 import com.owncloud.android.datamodel.OCFile
@@ -51,7 +51,7 @@ class EtmDownloaderFragment : EtmBaseFragment() {
 
         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()
             notifyDataSetChanged()
         }
@@ -130,10 +130,10 @@ class EtmDownloaderFragment : EtmBaseFragment() {
             Direction.DOWNLOAD,
             true
         )
-        vm.downloaderConnection.download(request)
+        vm.downloaderConnection.enqueue(request)
     }
 
-    private fun onDownloaderStatusChanged(status: Downloader.Status) {
+    private fun onDownloaderStatusChanged(status: TransferManager.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(
-        downloader: DownloaderImpl,
+        downloader: TransferManagerImpl,
         service: DownloaderService
     ) : LocalBinder<DownloaderService>(service),
-        Downloader by downloader
+        TransferManager by downloader
 
     @Inject
     lateinit var notificationsManager: AppNotificationManager
@@ -79,7 +79,7 @@ class DownloaderService : Service() {
 
     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() {
         AndroidInjection.inject(this)
@@ -99,7 +99,7 @@ class DownloaderService : Service() {
 
         val request = intent.getParcelableExtra(EXTRA_REQUEST) as Request
         val downloader = getDownloader(request.user)
-        downloader.download(request)
+        downloader.enqueue(request)
 
         logger.d(TAG, "Enqueued new download: ${request.uuid} ${request.file.remotePath}")
 
@@ -136,7 +136,7 @@ class DownloaderService : Service() {
         logger.d(TAG, "Stopping downloader service")
     }
 
-    private fun getDownloader(user: User): DownloaderImpl {
+    private fun getDownloader(user: User): TransferManagerImpl {
         val existingDownloader = downloaders[user.accountName]
         return if (existingDownloader != null) {
             existingDownloader
@@ -146,8 +146,8 @@ class DownloaderService : Service() {
                 { clientFactory.create(user) },
                 contentResolver
             )
-            val newDownloader = DownloaderImpl(runner, downloadTaskFactory)
-            newDownloader.registerDownloadListener(this::onDownloadUpdate)
+            val newDownloader = TransferManagerImpl(runner, downloadTaskFactory)
+            newDownloader.registerTransferListener(this::onDownloadUpdate)
             downloaders[user.accountName] = newDownloader
             newDownloader
         }

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

@@ -20,8 +20,7 @@
 package com.nextcloud.client.files.downloader
 
 import com.owncloud.android.datamodel.OCFile
-import java.lang.IllegalStateException
-import java.util.TreeMap
+import java.util.LinkedHashMap
 import java.util.UUID
 import kotlin.math.max
 import kotlin.math.min
@@ -46,9 +45,9 @@ internal class Registry(
     private val onTransferChanged: (Transfer) -> Unit,
     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
 
@@ -80,7 +79,7 @@ internal class Registry(
     fun startNext() {
         val freeThreads = max(0, maxRunning - runningQueue.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 runningTransfer = pendingTransfer.copy(state = TransferState.RUNNING)
             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 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(
         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
 
     /**
-     * Status snapshot of all downloads.
+     * Status snapshot of all transfers.
      */
     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.
      */
-    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)
 
@@ -68,31 +68,31 @@ interface Downloader {
     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
-     * @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.
      *
-     * 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
-     * @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 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 val downloadsRequiringStatusRedelivery: MutableSet<UUID> = mutableSetOf()
+    private val transfersRequiringStatusRedelivery: MutableSet<UUID> = mutableSetOf()
 
     override val isRunning: Boolean
         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)
         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)
         binder?.registerStatusListener(listener)
     }
 
-    override fun removeStatusListener(listener: (Downloader.Status) -> Unit) {
+    override fun removeStatusListener(listener: (TransferManager.Status) -> Unit) {
         statusListeners.remove(listener)
         binder?.removeStatusListener(listener)
     }
@@ -79,8 +82,8 @@ class DownloaderConnection(context: Context, val user: User) : LocalConnection<D
     override fun onBound(binder: IBinder) {
         super.onBound(binder)
         this.binder = binder as DownloaderService.Binder
-        downloadListeners.forEach { listener ->
-            binder.registerDownloadListener(listener)
+        transferListeners.forEach { listener ->
+            binder.registerTransferListener(listener)
         }
         statusListeners.forEach { 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.
      *
-     * 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() {
-        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)
             }
         }
-        downloadsRequiringStatusRedelivery.clear()
+        transfersRequiringStatusRedelivery.clear()
 
         if (statusListeners.isNotEmpty()) {
             binder?.status?.let { status ->
@@ -116,7 +119,7 @@ class DownloaderConnection(context: Context, val user: User) : LocalConnection<D
 
     override fun onUnbind() {
         super.onUnbind()
-        downloadListeners.forEach { binder?.removeDownloadListener(it) }
+        transferListeners.forEach { binder?.removeTransferListener(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
 
 /**
- * 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.
  *
  * @param runner Background task runner. It is important to provide runner that is not shared with UI code.
  * @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 taskFactory: DownloadTask.Factory,
     threads: Int = 1
-) : Downloader {
+) : TransferManager {
 
     companion object {
         const val PROGRESS_PERCENTAGE_MAX = 100
@@ -50,51 +50,54 @@ class DownloaderImpl(
     }
 
     private val registry = Registry(
-        onStartTransfer = this::onStartDownload,
-        onTransferChanged = this::onDownloadUpdate,
+        onStartTransfer = this::onStartTransfer,
+        onTransferChanged = this::onTransferUpdate,
         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 status: Downloader.Status
-        get() = Downloader.Status(
+    override val status: TransferManager.Status
+        get() = TransferManager.Status(
             pending = registry.pending,
             running = registry.running,
             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)
     }
 
-    override fun removeStatusListener(listener: (Downloader.Status) -> Unit) {
+    override fun removeStatusListener(listener: (TransferManager.Status) -> Unit) {
         statusListeners.remove(listener)
     }
 
-    override fun download(request: Request) {
+    override fun enqueue(request: Request) {
         registry.add(request)
         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(
-            task = downloadTask,
+            task = transferTask,
             onProgress = { progress: Int -> registry.progress(uuid, progress) },
             onResult = { result -> registry.complete(uuid, result.success, result.file); 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()) {
             val status = this.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.Transfer;
 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.jobs.BackgroundJobManager;
 import com.nextcloud.client.network.ClientFactory;
@@ -151,7 +151,7 @@ public class ContactListFragment extends FileFragment implements Injectable {
     @Inject UserAccountManager accountManager;
     @Inject ClientFactory clientFactory;
     @Inject BackgroundJobManager backgroundJobManager;
-    private DownloaderConnection fileDownloader;
+    private TransferManagerConnection fileDownloader;
 
     public static ContactListFragment newInstance(OCFile file, User user) {
         ContactListFragment frag = new ContactListFragment();
@@ -213,12 +213,12 @@ public class ContactListFragment extends FileFragment implements Injectable {
         ocFile = getArguments().getParcelable(FILE_NAME);
         setFile(ocFile);
         user = getArguments().getParcelable(USER);
-        fileDownloader = new DownloaderConnection(getActivity(), user);
-        fileDownloader.registerDownloadListener(this::onDownloadUpdate);
+        fileDownloader = new TransferManagerConnection(getActivity(), user);
+        fileDownloader.registerTransferListener(this::onDownloadUpdate);
         fileDownloader.bind();
         if (!ocFile.isDown()) {
             Request request = new Request(user, ocFile, Direction.DOWNLOAD);
-            fileDownloader.download(request);
+            fileDownloader.enqueue(request);
         } else {
             loadContactsTask.execute();
         }