Merge pull request #13015 from nextcloud/remove-foreground-worker-for-auto-upload

Create individual workers for every Autoupload Folder
This commit is contained in:
Alper Öztürk 2024-06-03 11:49:29 +02:00 committed by GitHub
commit 0459e97a84
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 235 additions and 167 deletions

View file

@ -119,9 +119,13 @@ interface BackgroundJobManager {
fun startImmediateFilesExportJob(files: Collection<OCFile>): LiveData<JobInfo?> fun startImmediateFilesExportJob(files: Collection<OCFile>): LiveData<JobInfo?>
fun schedulePeriodicFilesSyncJob() fun schedulePeriodicFilesSyncJob(syncedFolderID: Long)
/**
* Immediately start File Sync job for given syncFolderID.
*/
fun startImmediateFilesSyncJob( fun startImmediateFilesSyncJob(
syncedFolderID: Long,
overridePowerSaving: Boolean = false, overridePowerSaving: Boolean = false,
changedFiles: Array<String> = arrayOf<String>() changedFiles: Array<String> = arrayOf<String>()
) )
@ -163,5 +167,5 @@ interface BackgroundJobManager {
fun cancelAllJobs() fun cancelAllJobs()
fun schedulePeriodicHealthStatus() fun schedulePeriodicHealthStatus()
fun startHealthStatus() fun startHealthStatus()
fun bothFilesSyncJobsRunning(): Boolean fun bothFilesSyncJobsRunning(syncedFolderID: Long): Boolean
} }

View file

@ -404,37 +404,55 @@ internal class BackgroundJobManagerImpl(
workManager.cancelJob(JOB_PERIODIC_CALENDAR_BACKUP, user) workManager.cancelJob(JOB_PERIODIC_CALENDAR_BACKUP, user)
} }
override fun bothFilesSyncJobsRunning(): Boolean { override fun bothFilesSyncJobsRunning(syncedFolderID: Long): Boolean {
return workManager.isWorkRunning(JOB_PERIODIC_FILES_SYNC) && return workManager.isWorkRunning(JOB_PERIODIC_FILES_SYNC + "_" + syncedFolderID) &&
workManager.isWorkRunning(JOB_IMMEDIATE_FILES_SYNC) workManager.isWorkRunning(JOB_IMMEDIATE_FILES_SYNC + "_" + syncedFolderID)
} }
override fun schedulePeriodicFilesSyncJob() { override fun schedulePeriodicFilesSyncJob(
syncedFolderID: Long
) {
val arguments = Data.Builder()
.putLong(FilesSyncWork.SYNCED_FOLDER_ID, syncedFolderID)
.build()
val request = periodicRequestBuilder( val request = periodicRequestBuilder(
jobClass = FilesSyncWork::class, jobClass = FilesSyncWork::class,
jobName = JOB_PERIODIC_FILES_SYNC, jobName = JOB_PERIODIC_FILES_SYNC + "_" + syncedFolderID,
intervalMins = DEFAULT_PERIODIC_JOB_INTERVAL_MINUTES intervalMins = DEFAULT_PERIODIC_JOB_INTERVAL_MINUTES
).build() )
workManager.enqueueUniquePeriodicWork(JOB_PERIODIC_FILES_SYNC, ExistingPeriodicWorkPolicy.REPLACE, request) .setInputData(arguments)
.build()
workManager.enqueueUniquePeriodicWork(
JOB_PERIODIC_FILES_SYNC + "_" + syncedFolderID,
ExistingPeriodicWorkPolicy.REPLACE,
request
)
} }
override fun startImmediateFilesSyncJob( override fun startImmediateFilesSyncJob(
syncedFolderID: Long,
overridePowerSaving: Boolean, overridePowerSaving: Boolean,
changedFiles: Array<String> changedFiles: Array<String>
) { ) {
val arguments = Data.Builder() val arguments = Data.Builder()
.putBoolean(FilesSyncWork.OVERRIDE_POWER_SAVING, overridePowerSaving) .putBoolean(FilesSyncWork.OVERRIDE_POWER_SAVING, overridePowerSaving)
.putStringArray(FilesSyncWork.CHANGED_FILES, changedFiles) .putStringArray(FilesSyncWork.CHANGED_FILES, changedFiles)
.putLong(FilesSyncWork.SYNCED_FOLDER_ID, syncedFolderID)
.build() .build()
val request = oneTimeRequestBuilder( val request = oneTimeRequestBuilder(
jobClass = FilesSyncWork::class, jobClass = FilesSyncWork::class,
jobName = JOB_IMMEDIATE_FILES_SYNC jobName = JOB_IMMEDIATE_FILES_SYNC + "_" + syncedFolderID
) )
.setInputData(arguments) .setInputData(arguments)
.build() .build()
workManager.enqueueUniqueWork(JOB_IMMEDIATE_FILES_SYNC, ExistingWorkPolicy.APPEND, request) workManager.enqueueUniqueWork(
JOB_IMMEDIATE_FILES_SYNC + "_" + syncedFolderID,
ExistingWorkPolicy.APPEND,
request
)
} }
override fun scheduleOfflineSync() { override fun scheduleOfflineSync() {

View file

@ -12,6 +12,7 @@ import androidx.work.WorkerParameters
import com.nextcloud.client.device.PowerManagementService import com.nextcloud.client.device.PowerManagementService
import com.owncloud.android.datamodel.SyncedFolderProvider import com.owncloud.android.datamodel.SyncedFolderProvider
import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.utils.FilesSyncHelper
/** /**
* This work is triggered when OS detects change in media folders. * This work is triggered when OS detects change in media folders.
@ -23,7 +24,7 @@ import com.owncloud.android.lib.common.utils.Log_OC
class ContentObserverWork( class ContentObserverWork(
appContext: Context, appContext: Context,
private val params: WorkerParameters, private val params: WorkerParameters,
private val syncerFolderProvider: SyncedFolderProvider, private val syncedFolderProvider: SyncedFolderProvider,
private val powerManagementService: PowerManagementService, private val powerManagementService: PowerManagementService,
private val backgroundJobManager: BackgroundJobManager private val backgroundJobManager: BackgroundJobManager
) : Worker(appContext, params) { ) : Worker(appContext, params) {
@ -48,13 +49,17 @@ class ContentObserverWork(
} }
private fun checkAndStartFileSyncJob() { private fun checkAndStartFileSyncJob() {
val syncFolders = syncerFolderProvider.countEnabledSyncedFolders() > 0 if (!powerManagementService.isPowerSavingEnabled && syncedFolderProvider.countEnabledSyncedFolders() > 0) {
if (!powerManagementService.isPowerSavingEnabled && syncFolders) {
val changedFiles = mutableListOf<String>() val changedFiles = mutableListOf<String>()
for (uri in params.triggeredContentUris) { for (uri in params.triggeredContentUris) {
changedFiles.add(uri.toString()) changedFiles.add(uri.toString())
} }
backgroundJobManager.startImmediateFilesSyncJob(false, changedFiles.toTypedArray()) FilesSyncHelper.startFilesSyncForAllFolders(
syncedFolderProvider,
backgroundJobManager,
false,
changedFiles.toTypedArray()
)
} }
} }

View file

@ -11,11 +11,8 @@ package com.nextcloud.client.jobs
import android.content.ContentResolver import android.content.ContentResolver
import android.content.Context import android.content.Context
import android.content.res.Resources import android.content.res.Resources
import android.os.Build
import android.text.TextUtils import android.text.TextUtils
import androidx.core.app.NotificationCompat
import androidx.exifinterface.media.ExifInterface import androidx.exifinterface.media.ExifInterface
import androidx.work.ForegroundInfo
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.nextcloud.client.account.UserAccountManager import com.nextcloud.client.account.UserAccountManager
@ -28,7 +25,6 @@ import com.owncloud.android.R
import com.owncloud.android.datamodel.ArbitraryDataProvider import com.owncloud.android.datamodel.ArbitraryDataProvider
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl import com.owncloud.android.datamodel.ArbitraryDataProviderImpl
import com.owncloud.android.datamodel.FilesystemDataProvider import com.owncloud.android.datamodel.FilesystemDataProvider
import com.owncloud.android.datamodel.ForegroundServiceType
import com.owncloud.android.datamodel.MediaFolderType import com.owncloud.android.datamodel.MediaFolderType
import com.owncloud.android.datamodel.SyncedFolder import com.owncloud.android.datamodel.SyncedFolder
import com.owncloud.android.datamodel.SyncedFolderProvider import com.owncloud.android.datamodel.SyncedFolderProvider
@ -36,7 +32,6 @@ import com.owncloud.android.datamodel.UploadsStorageManager
import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.operations.UploadFileOperation import com.owncloud.android.operations.UploadFileOperation
import com.owncloud.android.ui.activity.SettingsActivity import com.owncloud.android.ui.activity.SettingsActivity
import com.owncloud.android.ui.notifications.NotificationUtils
import com.owncloud.android.utils.FileStorageUtils import com.owncloud.android.utils.FileStorageUtils
import com.owncloud.android.utils.FilesSyncHelper import com.owncloud.android.utils.FilesSyncHelper
import com.owncloud.android.utils.MimeType import com.owncloud.android.utils.MimeType
@ -64,80 +59,32 @@ class FilesSyncWork(
const val TAG = "FilesSyncJob" const val TAG = "FilesSyncJob"
const val OVERRIDE_POWER_SAVING = "overridePowerSaving" const val OVERRIDE_POWER_SAVING = "overridePowerSaving"
const val CHANGED_FILES = "changedFiles" const val CHANGED_FILES = "changedFiles"
const val FOREGROUND_SERVICE_ID = 414 const val SYNCED_FOLDER_ID = "syncedFolderId"
} }
@Suppress("MagicNumber") private lateinit var syncedFolder: SyncedFolder
private fun updateForegroundWorker(progressPercent: Int, useForegroundWorker: Boolean) {
if (!useForegroundWorker) {
return
}
// update throughout worker execution to give use feedback how far worker is
val notification = NotificationCompat.Builder(context, NotificationUtils.NOTIFICATION_CHANNEL_FILE_SYNC)
.setTicker(context.getString(R.string.autoupload_worker_foreground_info))
.setContentText(context.getString(R.string.autoupload_worker_foreground_info))
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle(context.getString(R.string.autoupload_worker_foreground_info))
.setOngoing(true)
.setProgress(100, progressPercent, false)
.build()
val foregroundInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ForegroundInfo(FOREGROUND_SERVICE_ID, notification, ForegroundServiceType.DataSync.getId())
} else {
ForegroundInfo(FOREGROUND_SERVICE_ID, notification)
}
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") @Suppress("MagicNumber")
override fun doWork(): Result { override fun doWork(): Result {
backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class)) val syncFolderId = inputData.getLong(SYNCED_FOLDER_ID, -1)
Log_OC.d(TAG, "File-sync worker started")
val changedFiles = inputData.getStringArray(CHANGED_FILES) val changedFiles = inputData.getStringArray(CHANGED_FILES)
if (canExitEarly(changedFiles)) { backgroundJobManager.logStartOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class) + "_" + syncFolderId)
Log_OC.d(TAG, "File-sync worker started for folder ID: $syncFolderId")
if (canExitEarly(changedFiles, syncFolderId)) {
val result = Result.success() val result = Result.success()
backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result) backgroundJobManager.logEndOfWorker(
BackgroundJobManagerImpl.formatClassTag(this::class) +
"_" + syncFolderId,
result
)
return result return result
} }
val resources = context.resources val resources = context.resources
val lightVersion = resources.getBoolean(R.bool.syncedFolder_light) val lightVersion = resources.getBoolean(R.bool.syncedFolder_light)
FilesSyncHelper.restartJobsIfNeeded( FilesSyncHelper.restartUploadsIfNeeded(
uploadsStorageManager, uploadsStorageManager,
userAccountManager, userAccountManager,
connectivityService, connectivityService,
@ -145,9 +92,13 @@ class FilesSyncWork(
) )
// Get changed files from ContentObserverWork (only images and videos) or by scanning filesystem // Get changed files from ContentObserverWork (only images and videos) or by scanning filesystem
Log_OC.d(TAG, "File-sync worker changed files from observer: " + changedFiles.contentToString()) Log_OC.d(
TAG,
"File-sync worker (${syncedFolder.remotePath}) changed files from observer: " +
changedFiles.contentToString()
)
collectChangedFiles(changedFiles) collectChangedFiles(changedFiles)
Log_OC.d(TAG, "File-sync worker finished checking files.") Log_OC.d(TAG, "File-sync worker (${syncedFolder.remotePath}) finished checking files.")
// Create all the providers we'll need // Create all the providers we'll need
val filesystemDataProvider = FilesystemDataProvider(contentResolver) val filesystemDataProvider = FilesystemDataProvider(contentResolver)
@ -155,41 +106,83 @@ class FilesSyncWork(
val dateFormat = SimpleDateFormat("yyyy:MM:dd HH:mm:ss", currentLocale) val dateFormat = SimpleDateFormat("yyyy:MM:dd HH:mm:ss", currentLocale)
dateFormat.timeZone = TimeZone.getTimeZone(TimeZone.getDefault().id) dateFormat.timeZone = TimeZone.getTimeZone(TimeZone.getDefault().id)
// start upload of changed / new files syncFolder(
val syncedFolders = syncedFolderProvider.syncedFolders context,
for ((index, syncedFolder) in syncedFolders.withIndex()) { resources,
updateForegroundWorker( lightVersion,
(50 + (index.toDouble() / syncedFolders.size.toDouble()) * 50).toInt(), filesystemDataProvider,
changedFiles.isNullOrEmpty() currentLocale,
) dateFormat,
if (syncedFolder.isEnabled) { syncedFolder
syncFolder( )
context,
resources, Log_OC.d(TAG, "File-sync worker (${syncedFolder.remotePath}) finished")
lightVersion,
filesystemDataProvider,
currentLocale,
dateFormat,
syncedFolder
)
}
}
Log_OC.d(TAG, "File-sync worker finished")
val result = Result.success() val result = Result.success()
backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result) backgroundJobManager.logEndOfWorker(
BackgroundJobManagerImpl.formatClassTag(this::class) +
"_" + syncFolderId,
result
)
return result return result
} }
private fun setSyncedFolder(syncedFolderID: Long): Boolean {
val syncedFolderTmp = syncedFolderProvider.getSyncedFolderByID(syncedFolderID)
if (syncedFolderTmp == null || !syncedFolderTmp.isEnabled || !syncedFolderTmp.isExisting) {
return false
}
syncedFolder = syncedFolderTmp
return true
}
@Suppress("ReturnCount")
private fun canExitEarly(changedFiles: Array<String>?, syncedFolderID: Long): Boolean {
// 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)) {
return true
}
if (syncedFolderID < 0) {
Log_OC.d(TAG, "File-sync kill worker since no valid syncedFolderID provided!")
return true
}
// or sync worker already running and no changed files to be processed
val alreadyRunning = backgroundJobManager.bothFilesSyncJobsRunning(syncedFolderID)
if (alreadyRunning && changedFiles.isNullOrEmpty()) {
Log_OC.d(
TAG,
"File-sync kill worker since another instance of the worker " +
"($syncedFolderID) seems to be running already!"
)
return true
}
if (!setSyncedFolder(syncedFolderID)) {
Log_OC.d(TAG, "File-sync kill worker since syncedFolder ($syncedFolderID) is not enabled!")
return true
}
if (syncedFolder.isChargingOnly &&
!powerManagementService.battery.isCharging &&
!powerManagementService.battery.isFull
) {
Log_OC.d(TAG, "File-sync kill worker since phone is not charging (${syncedFolder.localPath})!")
return true
}
return false
}
@Suppress("MagicNumber") @Suppress("MagicNumber")
private fun collectChangedFiles(changedFiles: Array<String>?) { private fun collectChangedFiles(changedFiles: Array<String>?) {
if (!changedFiles.isNullOrEmpty()) { if (!changedFiles.isNullOrEmpty()) {
FilesSyncHelper.insertChangedEntries(syncedFolderProvider, changedFiles) FilesSyncHelper.insertChangedEntries(syncedFolder, changedFiles)
} else { } else {
// Check every file in every synced folder for changes and update // Check every file in synced folder for changes and update
// filesystemDataProvider database (potentially needs a long time so use foreground worker) // filesystemDataProvider database (potentially needs a long time)
updateForegroundWorker(5, true) FilesSyncHelper.insertAllDBEntries(syncedFolder, powerManagementService)
FilesSyncHelper.insertAllDBEntries(syncedFolderProvider, powerManagementService)
updateForegroundWorker(50, true)
} }
} }

View file

@ -161,6 +161,9 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
@Inject @Inject
ConnectivityService connectivityService; ConnectivityService connectivityService;
@Inject
SyncedFolderProvider syncedFolderProvider;
@Inject PowerManagementService powerManagementService; @Inject PowerManagementService powerManagementService;
@Inject @Inject
@ -359,7 +362,8 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
backgroundJobManager, backgroundJobManager,
clock, clock,
viewThemeUtils, viewThemeUtils,
walledCheckCache); walledCheckCache,
syncedFolderProvider);
initContactsBackup(accountManager, backgroundJobManager); initContactsBackup(accountManager, backgroundJobManager);
notificationChannels(); notificationChannels();
@ -586,7 +590,8 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
final BackgroundJobManager backgroundJobManager, final BackgroundJobManager backgroundJobManager,
final Clock clock, final Clock clock,
final ViewThemeUtils viewThemeUtils, final ViewThemeUtils viewThemeUtils,
final WalledCheckCache walledCheckCache) { final WalledCheckCache walledCheckCache,
final SyncedFolderProvider syncedFolderProvider) {
updateToAutoUpload(); updateToAutoUpload();
cleanOldEntries(clock); cleanOldEntries(clock);
updateAutoUploadEntries(clock); updateAutoUploadEntries(clock);
@ -600,12 +605,12 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
} }
if (!preferences.isAutoUploadInitialized()) { if (!preferences.isAutoUploadInitialized()) {
backgroundJobManager.startImmediateFilesSyncJob(false, new String[]{}); FilesSyncHelper.startFilesSyncForAllFolders(syncedFolderProvider, backgroundJobManager,false, new String[]{});
preferences.setAutoUploadInit(true); preferences.setAutoUploadInit(true);
} }
FilesSyncHelper.scheduleFilesSyncIfNeeded(mContext, backgroundJobManager); FilesSyncHelper.scheduleFilesSyncForAllFoldersIfNeeded(mContext, syncedFolderProvider, backgroundJobManager);
FilesSyncHelper.restartJobsIfNeeded( FilesSyncHelper.restartUploadsIfNeeded(
uploadsStorageManager, uploadsStorageManager,
accountManager, accountManager,
connectivityService, connectivityService,

View file

@ -27,6 +27,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Observable; import java.util.Observable;
import javax.annotation.Nullable;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR;
@ -210,6 +212,29 @@ public class SyncedFolderProvider extends Observable {
} }
@Nullable
public SyncedFolder getSyncedFolderByID(Long syncedFolderID) {
SyncedFolder result = null;
Cursor cursor = mContentResolver.query(
ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
null,
ProviderMeta.ProviderTableMeta._ID + " =? ",
new String[]{syncedFolderID.toString()},
null
);
if (cursor != null && cursor.getCount() == 1 && cursor.moveToFirst()) {
result = createSyncedFolderFromCursor(cursor);
}
if (cursor != null) {
cursor.close();
}
return result;
}
/** /**
* Delete all synced folders for an account * Delete all synced folders for an account
* *

View file

@ -23,6 +23,7 @@ import com.nextcloud.client.network.ConnectivityService;
import com.nextcloud.client.network.WalledCheckCache; import com.nextcloud.client.network.WalledCheckCache;
import com.nextcloud.client.preferences.AppPreferences; import com.nextcloud.client.preferences.AppPreferences;
import com.owncloud.android.MainApp; import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.datamodel.UploadsStorageManager; import com.owncloud.android.datamodel.UploadsStorageManager;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.utils.theme.ViewThemeUtils; import com.owncloud.android.utils.theme.ViewThemeUtils;
@ -48,6 +49,7 @@ public class BootupBroadcastReceiver extends BroadcastReceiver {
@Inject Clock clock; @Inject Clock clock;
@Inject ViewThemeUtils viewThemeUtils; @Inject ViewThemeUtils viewThemeUtils;
@Inject WalledCheckCache walledCheckCache; @Inject WalledCheckCache walledCheckCache;
@Inject SyncedFolderProvider syncedFolderProvider;
/** /**
* Receives broadcast intent reporting that the system was just boot up. * * Receives broadcast intent reporting that the system was just boot up. *
@ -68,7 +70,9 @@ public class BootupBroadcastReceiver extends BroadcastReceiver {
backgroundJobManager, backgroundJobManager,
clock, clock,
viewThemeUtils, viewThemeUtils,
walledCheckCache); walledCheckCache,
syncedFolderProvider
);
MainApp.initContactsBackup(accountManager, backgroundJobManager); MainApp.initContactsBackup(accountManager, backgroundJobManager);
} else { } else {
Log_OC.d(TAG, "Getting wrong intent: " + intent.getAction()); Log_OC.d(TAG, "Getting wrong intent: " + intent.getAction());

View file

@ -571,7 +571,7 @@ class SyncedFoldersActivity :
} }
} }
if (syncedFolderDisplayItem.isEnabled) { if (syncedFolderDisplayItem.isEnabled) {
backgroundJobManager.startImmediateFilesSyncJob(overridePowerSaving = false) backgroundJobManager.startImmediateFilesSyncJob(syncedFolderDisplayItem.id, overridePowerSaving = false)
showBatteryOptimizationInfo() showBatteryOptimizationInfo()
} }
} }
@ -702,7 +702,7 @@ class SyncedFoldersActivity :
// existing synced folder setup to be updated // existing synced folder setup to be updated
syncedFolderProvider.updateSyncFolder(item) syncedFolderProvider.updateSyncFolder(item)
if (item.isEnabled) { if (item.isEnabled) {
backgroundJobManager.startImmediateFilesSyncJob(overridePowerSaving = false) backgroundJobManager.startImmediateFilesSyncJob(item.id, overridePowerSaving = false)
} else { } else {
val syncedFolderInitiatedKey = KEY_SYNCED_FOLDER_INITIATED_PREFIX + item.id val syncedFolderInitiatedKey = KEY_SYNCED_FOLDER_INITIATED_PREFIX + item.id
val arbitraryDataProvider = val arbitraryDataProvider =
@ -719,7 +719,7 @@ class SyncedFoldersActivity :
if (storedId != -1L) { if (storedId != -1L) {
item.id = storedId item.id = storedId
if (item.isEnabled) { if (item.isEnabled) {
backgroundJobManager.startImmediateFilesSyncJob(overridePowerSaving = false) backgroundJobManager.startImmediateFilesSyncJob(item.id, overridePowerSaving = false)
} else { } else {
val syncedFolderInitiatedKey = KEY_SYNCED_FOLDER_INITIATED_PREFIX + item.id val syncedFolderInitiatedKey = KEY_SYNCED_FOLDER_INITIATED_PREFIX + item.id
arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey) arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey)

View file

@ -34,6 +34,8 @@ import com.nextcloud.model.WorkerStateLiveData;
import com.owncloud.android.R; import com.owncloud.android.R;
import com.owncloud.android.databinding.UploadListLayoutBinding; import com.owncloud.android.databinding.UploadListLayoutBinding;
import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.datamodel.UploadsStorageManager; import com.owncloud.android.datamodel.UploadsStorageManager;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
@ -84,6 +86,9 @@ public class UploadListActivity extends FileActivity {
@Inject @Inject
BackgroundJobManager backgroundJobManager; BackgroundJobManager backgroundJobManager;
@Inject
SyncedFolderProvider syncedFolderProvider;
@Inject @Inject
LocalBroadcastManager localBroadcastManager; LocalBroadcastManager localBroadcastManager;
@ -193,7 +198,10 @@ public class UploadListActivity extends FileActivity {
} }
private void refresh() { private void refresh() {
backgroundJobManager.startImmediateFilesSyncJob(true,new String[]{}); FilesSyncHelper.startFilesSyncForAllFolders(syncedFolderProvider,
backgroundJobManager,
true,
new String[]{});
if (uploadsStorageManager.getFailedUploads().length > 0) { if (uploadsStorageManager.getFailedUploads().length > 0) {
new Thread(() -> { new Thread(() -> {
@ -316,10 +324,10 @@ public class UploadListActivity extends FileActivity {
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FileActivity.REQUEST_CODE__UPDATE_CREDENTIALS && resultCode == RESULT_OK) { if (requestCode == FileActivity.REQUEST_CODE__UPDATE_CREDENTIALS && resultCode == RESULT_OK) {
FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, FilesSyncHelper.restartUploadsIfNeeded(uploadsStorageManager,
userAccountManager, userAccountManager,
connectivityService, connectivityService,
powerManagementService); powerManagementService);
} }
} }
@ -339,10 +347,10 @@ public class UploadListActivity extends FileActivity {
} else { } else {
// already updated -> just retry! // already updated -> just retry!
FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, FilesSyncHelper.restartUploadsIfNeeded(uploadsStorageManager,
userAccountManager, userAccountManager,
connectivityService, connectivityService,
powerManagementService); powerManagementService);
} }
} else { } else {

View file

@ -146,34 +146,29 @@ public final class FilesSyncHelper {
} }
} }
public static void insertAllDBEntries(SyncedFolderProvider syncedFolderProvider, public static void insertAllDBEntries(SyncedFolder syncedFolder,
PowerManagementService powerManagementService) { PowerManagementService powerManagementService) {
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) { if (syncedFolder.isEnabled() &&
if (syncedFolder.isEnabled() && !(syncedFolder.isChargingOnly() &&
!(syncedFolder.isChargingOnly() && !powerManagementService.getBattery().isCharging() &&
!powerManagementService.getBattery().isCharging() && !powerManagementService.getBattery().isFull()
!powerManagementService.getBattery().isFull() )
) ) {
) { insertAllDBEntriesForSyncedFolder(syncedFolder);
insertAllDBEntriesForSyncedFolder(syncedFolder);
}
} }
} }
public static void insertChangedEntries(SyncedFolderProvider syncedFolderProvider, public static void insertChangedEntries(SyncedFolder syncedFolder,
String[] changedFiles) { String[] changedFiles) {
final ContentResolver contentResolver = MainApp.getAppContext().getContentResolver(); final ContentResolver contentResolver = MainApp.getAppContext().getContentResolver();
final FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver); final FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver);
for (String changedFileURI : changedFiles){ for (String changedFileURI : changedFiles){
String changedFile = getFileFromURI(changedFileURI); String changedFile = getFileFromURI(changedFileURI);
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) { if (syncedFolder.isEnabled() && syncedFolder.containsFile(changedFile)){
if (syncedFolder.isEnabled() && syncedFolder.containsFile(changedFile)){ File file = new File(changedFile);
File file = new File(changedFile); filesystemDataProvider.storeOrUpdateFileValue(changedFile,
filesystemDataProvider.storeOrUpdateFileValue(changedFile, file.lastModified(),file.isDirectory(),
file.lastModified(),file.isDirectory(), syncedFolder);
syncedFolder);
break;
}
} }
} }
} }
@ -249,10 +244,10 @@ public final class FilesSyncHelper {
} }
} }
public static void restartJobsIfNeeded(final UploadsStorageManager uploadsStorageManager, public static void restartUploadsIfNeeded(final UploadsStorageManager uploadsStorageManager,
final UserAccountManager accountManager, final UserAccountManager accountManager,
final ConnectivityService connectivityService, final ConnectivityService connectivityService,
final PowerManagementService powerManagementService) { final PowerManagementService powerManagementService) {
boolean accountExists; boolean accountExists;
boolean whileChargingOnly = true; boolean whileChargingOnly = true;
@ -316,11 +311,23 @@ public final class FilesSyncHelper {
}).start(); }).start();
} }
public static void scheduleFilesSyncIfNeeded(Context context, BackgroundJobManager jobManager) { public static void scheduleFilesSyncForAllFoldersIfNeeded(Context context, SyncedFolderProvider syncedFolderProvider, BackgroundJobManager jobManager) {
jobManager.schedulePeriodicFilesSyncJob(); for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
if (syncedFolder.isEnabled()) {
jobManager.schedulePeriodicFilesSyncJob(syncedFolder.getId());
}
}
if (context != null) { if (context != null) {
jobManager.scheduleContentObserverJob(); jobManager.scheduleContentObserverJob();
} }
} }
public static void startFilesSyncForAllFolders(SyncedFolderProvider syncedFolderProvider, BackgroundJobManager jobManager, boolean overridePowerSaving, String[] changedFiles) {
for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
if (syncedFolder.isEnabled()) {
jobManager.startImmediateFilesSyncJob(syncedFolder.getId(),overridePowerSaving,changedFiles);
}
}
}
} }

View file

@ -49,10 +49,10 @@ public final class ReceiversHelper {
DNSCache.clear(); DNSCache.clear();
walledCheckCache.clear(); walledCheckCache.clear();
if (connectivityService.getConnectivity().isConnected()) { if (connectivityService.getConnectivity().isConnected()) {
FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, FilesSyncHelper.restartUploadsIfNeeded(uploadsStorageManager,
accountManager, accountManager,
connectivityService, connectivityService,
powerManagementService); powerManagementService);
} }
} }
}; };
@ -76,10 +76,10 @@ public final class ReceiversHelper {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) { if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) {
FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, FilesSyncHelper.restartUploadsIfNeeded(uploadsStorageManager,
accountManager, accountManager,
connectivityService, connectivityService,
powerManagementService); powerManagementService);
} }
} }
}; };
@ -102,10 +102,10 @@ public final class ReceiversHelper {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (!powerManagementService.isPowerSavingEnabled()) { if (!powerManagementService.isPowerSavingEnabled()) {
FilesSyncHelper.restartJobsIfNeeded(uploadsStorageManager, FilesSyncHelper.restartUploadsIfNeeded(uploadsStorageManager,
accountManager, accountManager,
connectivityService, connectivityService,
powerManagementService); powerManagementService);
} }
} }
}; };

View file

@ -687,7 +687,6 @@
<string name="autoupload_hide_folder">Hide folder</string> <string name="autoupload_hide_folder">Hide folder</string>
<string name="autoupload_configure">Configure</string> <string name="autoupload_configure">Configure</string>
<string name="synced_folders_configure_folders">Configure folders</string> <string name="synced_folders_configure_folders">Configure folders</string>
<string name="autoupload_worker_foreground_info">Preparing auto upload</string>
<string name="empty" translatable="false" /> <string name="empty" translatable="false" />
<string name="test_server_button">Test server connection</string> <string name="test_server_button">Test server connection</string>

View file

@ -46,7 +46,7 @@ class ContentObserverWorkTest {
worker = ContentObserverWork( worker = ContentObserverWork(
appContext = context, appContext = context,
params = params, params = params,
syncerFolderProvider = folderProvider, syncedFolderProvider = folderProvider,
powerManagementService = powerManagementService, powerManagementService = powerManagementService,
backgroundJobManager = backgroundJobManager backgroundJobManager = backgroundJobManager
) )