Эх сурвалжийг харах

Merge pull request #12372 from nextcloud/make_sync_service_run_only_once

Make sync worker only run when needed
Alper Öztürk 1 жил өмнө
parent
commit
f0274584eb

+ 1 - 0
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManager.kt

@@ -163,4 +163,5 @@ interface BackgroundJobManager {
     fun cancelAllJobs()
     fun schedulePeriodicHealthStatus()
     fun startHealthStatus()
+    fun bothFilesSyncJobsRunning(): Boolean
 }

+ 6 - 0
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt

@@ -28,6 +28,7 @@ import com.nextcloud.client.documentscan.GeneratePdfFromImagesWork
 import com.nextcloud.client.jobs.download.FileDownloadWorker
 import com.nextcloud.client.jobs.upload.FileUploadWorker
 import com.nextcloud.client.preferences.AppPreferences
+import com.nextcloud.utils.extensions.isWorkRunning
 import com.nextcloud.utils.extensions.isWorkScheduled
 import com.owncloud.android.datamodel.OCFile
 import com.owncloud.android.operations.DownloadType
@@ -403,6 +404,11 @@ internal class BackgroundJobManagerImpl(
         workManager.cancelJob(JOB_PERIODIC_CALENDAR_BACKUP, user)
     }
 
+    override fun bothFilesSyncJobsRunning(): Boolean {
+        return workManager.isWorkRunning(JOB_PERIODIC_FILES_SYNC) &&
+            workManager.isWorkRunning(JOB_IMMEDIATE_FILES_SYNC)
+    }
+
     override fun schedulePeriodicFilesSyncJob() {
         val request = periodicRequestBuilder(
             jobClass = FilesSyncWork::class,

+ 36 - 5
app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt

@@ -91,18 +91,50 @@ class FilesSyncWork(
         setForegroundAsync(foregroundInfo)
     }
 
+    private fun canExitEarly(changedFiles: Array<String>?): Boolean {
+        var canExitEarly = false
+        // If we are in power save mode better to postpone scan and upload
+        val overridePowerSaving = inputData.getBoolean(OVERRIDE_POWER_SAVING, false)
+        if ((powerManagementService.isPowerSavingEnabled && !overridePowerSaving)) {
+            canExitEarly = true
+        }
+
+        // or sync worker already running and no changed files to be processed
+        val alreadyRunning = backgroundJobManager.bothFilesSyncJobsRunning()
+        if (alreadyRunning && changedFiles.isNullOrEmpty()) {
+            Log_OC.d(TAG, "File-sync kill worker since another instance of the worker seems to be running already!")
+            canExitEarly = true
+        }
+
+        if (!syncedFolderProvider.syncedFolders.any { it.isEnabled }) {
+            Log_OC.d(TAG, "File-sync kill worker since no sync folder is enabled!")
+            canExitEarly = true
+        }
+
+        if (syncedFolderProvider.syncedFolders.all { it.isChargingOnly } &&
+            !powerManagementService.battery.isCharging &&
+            !powerManagementService.battery.isFull
+        ) {
+            Log_OC.d(TAG, "File-sync kill worker since phone is not charging!")
+            canExitEarly = true
+        }
+
+        return canExitEarly
+    }
+
     @Suppress("MagicNumber")
     override fun doWork(): Result {
         backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class))
         Log_OC.d(TAG, "File-sync worker started")
 
-        val overridePowerSaving = inputData.getBoolean(OVERRIDE_POWER_SAVING, false)
-        // If we are in power save mode, better to postpone upload
-        if (powerManagementService.isPowerSavingEnabled && !overridePowerSaving) {
+        val changedFiles = inputData.getStringArray(CHANGED_FILES)
+
+        if (canExitEarly(changedFiles)) {
             val result = Result.success()
             backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result)
             return result
         }
+
         val resources = context.resources
         val lightVersion = resources.getBoolean(R.bool.syncedFolder_light)
         FilesSyncHelper.restartJobsIfNeeded(
@@ -113,7 +145,6 @@ class FilesSyncWork(
         )
 
         // Get changed files from ContentObserverWork (only images and videos) or by scanning filesystem
-        val changedFiles = inputData.getStringArray(CHANGED_FILES)
         Log_OC.d(TAG, "File-sync worker changed files from observer: " + changedFiles.contentToString())
         collectChangedFiles(changedFiles)
         Log_OC.d(TAG, "File-sync worker finished checking files.")
@@ -157,7 +188,7 @@ class FilesSyncWork(
             // Check every file in every synced folder for changes and update
             // filesystemDataProvider database (potentially needs a long time so use foreground worker)
             updateForegroundWorker(5, true)
-            FilesSyncHelper.insertAllDBEntries(syncedFolderProvider)
+            FilesSyncHelper.insertAllDBEntries(syncedFolderProvider, powerManagementService)
             updateForegroundWorker(50, true)
         }
     }

+ 12 - 11
app/src/main/java/com/nextcloud/utils/extensions/WorkManagerExtensions.kt

@@ -13,23 +13,24 @@ import com.google.common.util.concurrent.ListenableFuture
 import com.owncloud.android.lib.common.utils.Log_OC
 import java.util.concurrent.ExecutionException
 
-fun WorkManager.isWorkScheduled(tag: String): Boolean {
-    val statuses: ListenableFuture<List<WorkInfo>> = this.getWorkInfosByTag(tag)
-    var running = false
+private const val TAG = "WorkManager"
+
+fun WorkManager.isWorkRunning(tag: String): Boolean = checkWork(tag, listOf(WorkInfo.State.RUNNING))
+
+fun WorkManager.isWorkScheduled(tag: String): Boolean =
+    checkWork(tag, listOf(WorkInfo.State.RUNNING, WorkInfo.State.ENQUEUED))
+
+private fun WorkManager.checkWork(tag: String, stateConditions: List<WorkInfo.State>): Boolean {
+    val statuses: ListenableFuture<List<WorkInfo>> = getWorkInfosByTag(tag)
     var workInfoList: List<WorkInfo> = emptyList()
 
     try {
         workInfoList = statuses.get()
     } catch (e: ExecutionException) {
-        Log_OC.d("Worker", "ExecutionException in isWorkScheduled: $e")
+        Log_OC.d(TAG, "ExecutionException in checkWork: $e")
     } catch (e: InterruptedException) {
-        Log_OC.d("Worker", "InterruptedException in isWorkScheduled: $e")
-    }
-
-    for (workInfo in workInfoList) {
-        val state = workInfo.state
-        running = running || (state == WorkInfo.State.RUNNING || state == WorkInfo.State.ENQUEUED)
+        Log_OC.d(TAG, "InterruptedException in checkWork: $e")
     }
 
-    return running
+    return workInfoList.any { workInfo -> stateConditions.contains(workInfo.state) }
 }

+ 8 - 2
app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java

@@ -145,9 +145,15 @@ public final class FilesSyncHelper {
         }
     }
 
-    public static void insertAllDBEntries(SyncedFolderProvider syncedFolderProvider) {
+    public static void insertAllDBEntries(SyncedFolderProvider syncedFolderProvider,
+                                          PowerManagementService powerManagementService) {
         for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
-            if (syncedFolder.isEnabled()) {
+            if (syncedFolder.isEnabled() &&
+                !(syncedFolder.isChargingOnly() &&
+                    !powerManagementService.getBattery().isCharging() &&
+                    !powerManagementService.getBattery().isFull()
+                )
+            ) {
                 insertAllDBEntriesForSyncedFolder(syncedFolder);
             }
         }