@@ -19,7 +19,6 @@ import androidx.work.WorkQuery
19
19
import androidx.work.WorkerParameters
20
20
import at.bitfire.davdroid.InvalidAccountException
21
21
import at.bitfire.davdroid.R
22
- import at.bitfire.davdroid.log.Logger
23
22
import at.bitfire.davdroid.settings.AccountSettings
24
23
import at.bitfire.davdroid.sync.AddressBookSyncer
25
24
import at.bitfire.davdroid.sync.CalendarSyncer
@@ -30,24 +29,20 @@ import at.bitfire.davdroid.sync.Syncer
30
29
import at.bitfire.davdroid.sync.TaskSyncer
31
30
import at.bitfire.davdroid.ui.NotificationRegistry
32
31
import at.bitfire.ical4android.TaskProvider
33
- import dagger.hilt.EntryPoint
34
- import dagger.hilt.InstallIn
35
- import dagger.hilt.android.EntryPointAccessors
36
- import dagger.hilt.components.SingletonComponent
37
32
import kotlinx.coroutines.CoroutineDispatcher
38
33
import kotlinx.coroutines.delay
39
34
import kotlinx.coroutines.flow.Flow
40
35
import kotlinx.coroutines.flow.map
41
36
import kotlinx.coroutines.runInterruptible
42
37
import kotlinx.coroutines.withContext
43
38
import java.util.Collections
39
+ import java.util.logging.Logger
40
+ import javax.inject.Inject
41
+ import javax.inject.Provider
44
42
45
43
abstract class BaseSyncWorker (
46
44
context : Context ,
47
45
private val workerParams : WorkerParameters ,
48
- private val accountSettingsFactory : AccountSettings .Factory ,
49
- private val notificationRegistry : NotificationRegistry ,
50
- private val syncConditionsFactory : SyncConditions .Factory ,
51
46
private val syncDispatcher : CoroutineDispatcher
52
47
) : CoroutineWorker(context, workerParams) {
53
48
@@ -124,19 +119,29 @@ abstract class BaseSyncWorker(
124
119
125
120
}
126
121
127
- // We don't inject the Syncers in our constructor because that would generate
128
- // every syncer object regardless of whether it's even used for the synced authority (useless overhead).
129
- @EntryPoint
130
- @InstallIn(SingletonComponent ::class )
131
- interface BaseSyncWorkerEntryPoint {
132
- fun addressBookSyncer (): AddressBookSyncer
133
- fun calendarSyncer (): CalendarSyncer
134
- fun jtxSyncer (): JtxSyncer
135
- fun taskSyncer (): TaskSyncer
136
- }
137
- private val entryPoint = EntryPointAccessors .fromApplication<BaseSyncWorkerEntryPoint >(context)
122
+ @Inject
123
+ lateinit var accountSettingsFactory: AccountSettings .Factory
124
+
125
+ @Inject
126
+ lateinit var addressBookSyncer: Provider <AddressBookSyncer >
127
+
128
+ @Inject
129
+ lateinit var calendarSyncer: Provider <CalendarSyncer >
130
+
131
+ @Inject
132
+ lateinit var jtxSyncer: Provider <JtxSyncer >
133
+
134
+ @Inject
135
+ lateinit var logger: Logger
136
+
137
+ @Inject
138
+ lateinit var notificationRegistry: NotificationRegistry
139
+
140
+ @Inject
141
+ lateinit var syncConditionsFactory: SyncConditions .Factory
138
142
139
- private val notificationManager = NotificationManagerCompat .from(applicationContext)
143
+ @Inject
144
+ lateinit var taskSyncer: Provider <TaskSyncer >
140
145
141
146
142
147
override suspend fun doWork (): Result {
@@ -148,10 +153,10 @@ abstract class BaseSyncWorker(
148
153
val authority = inputData.getString(INPUT_AUTHORITY ) ? : throw IllegalArgumentException (" $INPUT_AUTHORITY required" )
149
154
150
155
val syncTag = commonTag(account, authority)
151
- Logger .log .info(" ${javaClass.simpleName} called for $syncTag " )
156
+ logger .info(" ${javaClass.simpleName} called for $syncTag " )
152
157
153
158
if (! runningSyncs.add(syncTag)) {
154
- Logger .log .info(" There's already another worker running for $syncTag , skipping" )
159
+ logger .info(" There's already another worker running for $syncTag , skipping" )
155
160
return Result .success()
156
161
}
157
162
@@ -160,7 +165,7 @@ abstract class BaseSyncWorker(
160
165
accountSettingsFactory.forAccount(account)
161
166
} catch (e: InvalidAccountException ) {
162
167
val workId = workerParams.id
163
- Logger .log .warning(" Account $account doesn't exist anymore, cancelling worker $workId " )
168
+ logger .warning(" Account $account doesn't exist anymore, cancelling worker $workId " )
164
169
165
170
val workManager = WorkManager .getInstance(applicationContext)
166
171
workManager.cancelWorkById(workId)
@@ -169,26 +174,26 @@ abstract class BaseSyncWorker(
169
174
}
170
175
171
176
if (inputData.getBoolean(INPUT_MANUAL , false ))
172
- Logger .log .info(" Manual sync, skipping network checks" )
177
+ logger .info(" Manual sync, skipping network checks" )
173
178
else {
174
179
val syncConditions = syncConditionsFactory.create(accountSettings)
175
180
176
181
// check internet connection
177
182
if (! syncConditions.internetAvailable()) {
178
- Logger .log .info(" WorkManager started SyncWorker without Internet connection. Aborting." )
183
+ logger .info(" WorkManager started SyncWorker without Internet connection. Aborting." )
179
184
return Result .success()
180
185
}
181
186
182
187
// check WiFi restriction
183
188
if (! syncConditions.wifiConditionsMet()) {
184
- Logger .log .info(" WiFi conditions not met. Won't run periodic sync." )
189
+ logger .info(" WiFi conditions not met. Won't run periodic sync." )
185
190
return Result .success()
186
191
}
187
192
}
188
193
189
194
return doSyncWork(account, authority, accountSettings)
190
195
} finally {
191
- Logger .log .info(" ${javaClass.simpleName} finished for $syncTag " )
196
+ logger .info(" ${javaClass.simpleName} finished for $syncTag " )
192
197
runningSyncs - = syncTag
193
198
}
194
199
}
@@ -198,19 +203,19 @@ abstract class BaseSyncWorker(
198
203
authority : String ,
199
204
accountSettings : AccountSettings
200
205
): Result = withContext(syncDispatcher) {
201
- Logger .log .info(" Running ${javaClass.name} : account=$account , authority=$authority " )
206
+ logger .info(" Running ${javaClass.name} : account=$account , authority=$authority " )
202
207
203
208
// What are we going to sync? Select syncer based on authority
204
209
val syncer: Syncer = when (authority) {
205
210
applicationContext.getString(R .string.address_books_authority) ->
206
- entryPoint. addressBookSyncer()
211
+ addressBookSyncer.get ()
207
212
CalendarContract .AUTHORITY ->
208
- entryPoint. calendarSyncer()
213
+ calendarSyncer.get ()
209
214
TaskProvider .ProviderName .JtxBoard .authority ->
210
- entryPoint. jtxSyncer()
215
+ jtxSyncer.get ()
211
216
TaskProvider .ProviderName .OpenTasks .authority,
212
217
TaskProvider .ProviderName .TasksOrg .authority ->
213
- entryPoint. taskSyncer()
218
+ taskSyncer.get ()
214
219
else ->
215
220
throw IllegalArgumentException (" Invalid authority $authority " )
216
221
}
@@ -243,21 +248,21 @@ abstract class BaseSyncWorker(
243
248
244
249
// On soft errors the sync is retried a few times before considered failed
245
250
if (result.hasSoftError()) {
246
- Logger .log .warning(" Soft error while syncing: result=$result , stats=${result.stats} " )
251
+ logger .warning(" Soft error while syncing: result=$result , stats=${result.stats} " )
247
252
if (runAttemptCount < MAX_RUN_ATTEMPTS ) {
248
253
val blockDuration = result.delayUntil - System .currentTimeMillis() / 1000
249
- Logger .log .warning(" Waiting for $blockDuration seconds, before retrying ..." )
254
+ logger .warning(" Waiting for $blockDuration seconds, before retrying ..." )
250
255
251
256
// We block the SyncWorker here so that it won't be started by the sync framework immediately again.
252
257
// This should be replaced by proper work scheduling as soon as we don't depend on the sync framework anymore.
253
258
if (blockDuration > 0 )
254
259
delay(blockDuration * 1000 )
255
260
256
- Logger .log .warning(" Retrying on soft error (attempt $runAttemptCount of $MAX_RUN_ATTEMPTS )" )
261
+ logger .warning(" Retrying on soft error (attempt $runAttemptCount of $MAX_RUN_ATTEMPTS )" )
257
262
return @withContext Result .retry()
258
263
}
259
264
260
- Logger .log .warning(" Max retries on soft errors reached ($runAttemptCount of $MAX_RUN_ATTEMPTS ). Treating as failed" )
265
+ logger .warning(" Max retries on soft errors reached ($runAttemptCount of $MAX_RUN_ATTEMPTS ). Treating as failed" )
261
266
262
267
notificationRegistry.notifyIfPossible(NotificationRegistry .NOTIFY_SYNC_ERROR , tag = softErrorNotificationTag) {
263
268
NotificationCompat .Builder (applicationContext, NotificationRegistry .CHANNEL_SYNC_IO_ERRORS )
@@ -275,6 +280,7 @@ abstract class BaseSyncWorker(
275
280
}
276
281
277
282
// If no soft error found, dismiss sync error notification
283
+ val notificationManager = NotificationManagerCompat .from(applicationContext)
278
284
notificationManager.cancel(
279
285
softErrorNotificationTag,
280
286
NotificationRegistry .NOTIFY_SYNC_ERROR
@@ -283,7 +289,7 @@ abstract class BaseSyncWorker(
283
289
// On a hard error - fail with an error message
284
290
// Note: SyncManager should have notified the user
285
291
if (result.hasHardError()) {
286
- Logger .log .warning(" Hard error while syncing: result=$result , stats=${result.stats} " )
292
+ logger .warning(" Hard error while syncing: result=$result , stats=${result.stats} " )
287
293
return @withContext Result .failure(syncResult)
288
294
}
289
295
}
0 commit comments