Pending sync not shown in some cases
When a sync has not been initiated by the sync framework yet, there's no pending worker, and we currently don't show that a sync is pending, which is confusing.
In AccountProgressUseCase (probably) just add a callback flow pendingInSyncFramework with ContentResolver.addStatusChangeListener() checking for pending and combine that flow in AccountProgressUseCase.invoke.
Might be impossible, since:
- Android's
ContentResolver.isSyncPending(account, authority)cannot, on its own, tell us if the pending sync is user-initiated or a periodic sync. - periodic syncs always exist for calendar !?
- Android's
ContentResolver.isSyncPending(account, authority)cannot, on its own, tell us if the pending sync is user-initiated or a periodic sync.
Periodic syncs should never be done over the sync framework.
But even if they would, I think they wouldn't be pending? Because that had worked too back then when we didn't have WorkManager yet.
hmm. it actually works just fine on my A13 emulator. But on my A15 emulator the calendar authority syncs stay pending forever ...
On Android 13 (works)
Here are logs from when the davx5 sync should be recognized as pending:
emu64x:/ $ dumpsys content | grep calendar
JobId=100004 [email protected]/bitfire.at.davdroid u0 [com.android.calendar] LOCAL ExpectedIn=-1s STANDBY-EXEMPTED(TOP) Reason=10084 Owner={u0a194 at.bitfire.davdroid [10] [ACTIVE]} [upload=true ]
com.android.calendar 1 true Total 4 0 0 0 3 4 11 0 0 15s USER SUCCESS
com.android.calendar 1 false Total 0 0 0 0 0 0 0 0 0 0s
com.android.calendar : 4/66% 3s/50%
#1 : 2025-05-07 11:44:04 USER 0.4s [email protected]/bitfire.at.davdroid u0 com.android.calendar ws.xsoh.etar
#2 : 2025-05-07 11:43:58 USER 1.1s 6 [email protected]/bitfire.at.davdroid u0 com.android.calendar ws.xsoh.etar
#3 : 2025-05-07 11:42:21 OTHER 0.5s 01:36 [email protected]/bitfire.at.davdroid u0 com.android.calendar ServiceChanged
#4 : 2025-05-07 11:42:04 OTHER 1.4s 16 [email protected]/bitfire.at.davdroid u0 com.android.calendar com.android.providers.calendar
#1 : 2025-05-07 11:44:04 USER [email protected]/bitfire.at.davdroid u0 com.android.calendar Bundle[{ignore_settings=true, force=true, ignore_backoff=true}]
#2 : 2025-05-07 11:43:58 USER [email protected]/bitfire.at.davdroid u0 com.android.calendar Bundle[{ignore_settings=true, force=true, ignore_backoff=true}]
[email protected]/bitfire.at.davdroid u0 [com.android.calendar]
Calendar subscriptions/at.bitfire.icsdroid u0 [com.android.calendar]
ServiceInfo: SyncAdapterType {name=com.google.android.calendar.tasks, type=com.google, userVisible=true, supportsUploading=false, isAlwaysSyncable=false, allowParallelSyncs=true, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.android.apps.calendar.vagabond.tasks.impl.sync.PlatformSync$SyncService}, uid 10141
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=bitfire.at.davdroid, userVisible=false, supportsUploading=true, isAlwaysSyncable=true, allowParallelSyncs=true, settingsActivity=null, packageName=at.bitfire.davdroid}, ComponentInfo{at.bitfire.davdroid/at.bitfire.davdroid.sync.CalendarsSyncAdapterService}, uid 10194
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=at.bitfire.icsdroid, userVisible=true, supportsUploading=false, isAlwaysSyncable=true, allowParallelSyncs=true, settingsActivity=null, packageName=at.bitfire.icsdroid}, ComponentInfo{at.bitfire.icsdroid/at.bitfire.icsdroid.SyncAdapterService}, uid 10174
ServiceInfo: SyncAdapterType {name=com.google.android.calendar, type=com.google, userVisible=true, supportsUploading=false, isAlwaysSyncable=false, allowParallelSyncs=true, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.calendar.v2a.shared.sync.impl.android.PlatformSyncShell$SyncAdapterService}, uid 10141
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=com.google, userVisible=true, supportsUploading=true, isAlwaysSyncable=false, allowParallelSyncs=false, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.android.syncadapters.calendar.CalendarSyncAdapterService}, uid 10141
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=com.google.android.gm.exchange, userVisible=true, supportsUploading=true, isAlwaysSyncable=false, allowParallelSyncs=true, settingsActivity=null, packageName=com.google.android.gm}, ComponentInfo{com.google.android.gm/com.android.exchange.service.CalendarSyncAdapterService}, uid 10145
com.android.calendar: pid=554 uid=1000 user=0 target=58a043e
com.android.calendar/instances/when: pid=554 uid=1000 user=0 target=c91dfaf
com.android.calendar/events: pid=554 uid=1000 user=0 target=c91dfaf
com.android.calendar/calendars: pid=554 uid=1000 user=0 target=c91dfaf
Here for when davx5 sync should not be recognized as pending:
emu64x:/ $ dumpsys content | grep calendar
com.android.calendar 1 true Total 5 0 0 0 3 4 12 0 0 16s LOCAL SUCCESS
com.android.calendar 1 false Total 0 0 0 0 0 0 0 0 0 0s
com.android.calendar : 5/71% 4s/59%
#1 : 2025-05-07 11:45:13 LOCAL 1.5s [email protected]/bitfire.at.davdroid u0 com.android.calendar com.android.providers.calendar
#2 : 2025-05-07 11:44:04 USER 0.4s 01:09 [email protected]/bitfire.at.davdroid u0 com.android.calendar ws.xsoh.etar
#3 : 2025-05-07 11:43:58 USER 1.1s 6 [email protected]/bitfire.at.davdroid u0 com.android.calendar ws.xsoh.etar
#4 : 2025-05-07 11:42:21 OTHER 0.5s 01:36 [email protected]/bitfire.at.davdroid u0 com.android.calendar ServiceChanged
#5 : 2025-05-07 11:42:04 OTHER 1.4s 16 [email protected]/bitfire.at.davdroid u0 com.android.calendar com.android.providers.calendar
#1 : 2025-05-07 11:45:13 LOCAL [email protected]/bitfire.at.davdroid u0 com.android.calendar Bundle[{upload=true}]
#2 : 2025-05-07 11:44:04 USER [email protected]/bitfire.at.davdroid u0 com.android.calendar Bundle[{ignore_settings=true, force=true, ignore_backoff=true}]
#3 : 2025-05-07 11:43:58 USER [email protected]/bitfire.at.davdroid u0 com.android.calendar Bundle[{ignore_settings=true, force=true, ignore_backoff=true}]
[email protected]/bitfire.at.davdroid u0 [com.android.calendar]
Calendar subscriptions/at.bitfire.icsdroid u0 [com.android.calendar]
ServiceInfo: SyncAdapterType {name=com.google.android.calendar.tasks, type=com.google, userVisible=true, supportsUploading=false, isAlwaysSyncable=false, allowParallelSyncs=true, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.android.apps.calendar.vagabond.tasks.impl.sync.PlatformSync$SyncService}, uid 10141
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=bitfire.at.davdroid, userVisible=false, supportsUploading=true, isAlwaysSyncable=true, allowParallelSyncs=true, settingsActivity=null, packageName=at.bitfire.davdroid}, ComponentInfo{at.bitfire.davdroid/at.bitfire.davdroid.sync.CalendarsSyncAdapterService}, uid 10194
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=at.bitfire.icsdroid, userVisible=true, supportsUploading=false,
Android 15 (wrongly shows as pending)
Now here is for the Android 15 emulator where davx5 sync is always seen as pending. Regardless of whether it is truly pending.
Logs for when it should truly be pending:
JobId=9 [email protected]/com.google u0 [com.android.calendar] LOCAL ExpectedIn=20s STANDBY-EXEMPTED(TOP) Reason=10094 Owner={u0a149 com.google.android.calendar [10] [ACTIVE]} [upload=true ]
JobId=32 [email protected]/com.google u0 [com.android.calendar] PERIODIC Reason=Periodic (period=1d00h00m00s flex=57m36s) Owner={u0a149 com.google.android.calendar [10] [ACTIVE]} [sync_extra_get_settings=true sync_extra_get_recent_notifications=true sync_extra_get_default_notifications=true sync_periodic=true ]
JobId=33 [email protected]/com.google u0 [com.google.android.calendar] PERIODIC Reason=Periodic (period=1d00h00m00s flex=57m36s) Owner={u0a149 com.google.android.calendar [10] [ACTIVE]} [periodic_sync=true run_sync=true ]
JobId=44 [email protected]/com.google u0 [com.google.android.calendar.tasks] PERIODIC Reason=Periodic (period=1d00h00m00s flex=57m36s) Owner={u0a149 com.google.android.calendar [10] [ACTIVE]} [sync_reason=PERIODIC ]
com.android.calendar 1 true Total 63 0 0 3 161 29 256 0 5 1m40s LOCAL SUCCESS
com.google.android.calendar 1 true Total 0 0 0 0 0 5 5 0 0 4s OTHER SUCCESS
com.google.android.calendar.tasks 1 true Total 0 0 0 0 0 2 2 0 0 1s OTHER SUCCESS
com.android.calendar 1 false Total 0 0 0 0 1 2 3 0 0 4s USER SUCCESS
com.android.calendar : 6/46% 3s/45%
#1 : 2025-05-07 11:55:05 LOCAL 0.0s [email protected]/com.google u0 com.android.calendar com.android.providers.calendar
#2 : 2025-05-07 11:52:17 USER 0.3s 02:47 [email protected]/com.google u0 com.android.calendar com.google.android.calendar
#3 : 2025-05-07 11:52:17 USER 0.5s 0 [email protected]/com.google u0 com.android.calendar com.google.android.calendar
#4 : 2025-05-07 11:52:17 USER 0.2s 0 [email protected]/com.google u0 com.android.calendar com.google.android.calendar
#5 : 2025-05-07 11:52:15 USER 0.4s [email protected]/bitfire.at.davdroid u0 com.android.calendar ws.xsoh.etar
#6 : 2025-05-07 11:52:15 USER 2.0s 1 [email protected]/com.google u0 com.android.calendar ws.xsoh.etar
#1 : 2025-05-07 11:55:05 LOCAL [email protected]/com.google u0 com.android.calendar Bundle[{upload=true}]
#2 : 2025-05-07 11:52:17 USER [email protected]/com.google u0 com.android.calendar Bundle[{ignore_settings=true, force=true, ignore_backoff=true, feed_internal=en.usa#[email protected]}]
#3 : 2025-05-07 11:52:17 USER [email protected]/com.google u0 com.android.calendar Bundle[{ignore_settings=true, force=true, ignore_backoff=true, feed_internal=de.austrian#[email protected]}]
#4 : 2025-05-07 11:52:17 USER [email protected]/com.google u0 com.android.calendar Bundle[{ignore_settings=true, force=true, ignore_backoff=true, [email protected]}]
#5 : 2025-05-07 11:52:15 USER [email protected]/bitfire.at.davdroid u0 com.android.calendar Bundle[{ignore_settings=true, force=true, ignore_backoff=true}]
#6 : 2025-05-07 11:52:15 USER [email protected]/com.google u0 com.android.calendar Bundle[{ignore_settings=true, force=true, ignore_backoff=true}]
[email protected]/com.google u0 [com.android.calendar]
2025-05-07 11:52:18 success Source=USER Elapsed=0s Reason=10149 Exemption=fg Extras=[ignore_settings=true force=true ignore_backoff=true feed_internal=en.usa#[email protected] ]
2025-05-07 11:52:17 success Source=USER Elapsed=0s Reason=10149 Exemption=fg Extras=[ignore_settings=true force=true ignore_backoff=true feed_internal=de.austrian#[email protected] ]
[email protected]/com.google u0 [com.google.android.calendar]
[email protected]/com.google u0 [com.google.android.calendar.tasks]
[email protected]/bitfire.at.davdroid u0 [com.android.calendar]
ServiceInfo: SyncAdapterType {name=com.google.android.calendar.tasks, type=com.google, userVisible=true, supportsUploading=false, isAlwaysSyncable=false, allowParallelSyncs=true, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.android.apps.calendar.vagabond.tasks.impl.sync.PlatformSync$SyncService}, uid 10149
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=bitfire.at.davdroid, userVisible=false, supportsUploading=true, isAlwaysSyncable=true, allowParallelSyncs=true, settingsActivity=null, packageName=at.bitfire.davdroid}, ComponentInfo{at.bitfire.davdroid/at.bitfire.davdroid.sync.CalendarsSyncAdapterService}, uid 10222
ServiceInfo: SyncAdapterType {name=com.google.android.calendar, type=com.google, userVisible=true, supportsUploading=false, isAlwaysSyncable=false, allowParallelSyncs=true, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.calendar.v2a.shared.sync.impl.android.PlatformSyncShell$SyncAdapterService}, uid 10149
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=com.google, userVisible=true, supportsUploading=true, isAlwaysSyncable=false, allowParallelSyncs=false, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.android.syncadapters.calendar.CalendarSyncAdapterService}, uid 10149
com.android.calendar: pid=581 uid=1000 user=0 target=e198d8d
com.android.calendar/instances/when: pid=581 uid=1000 user=0 target=e677066
com.android.calendar/events: pid=581 uid=1000 user=0 target=e677066
com.android.calendar/calendars: pid=581 uid=1000 user=0 target=e677066
com.google.android.gms.phenotype/com.google.android.gms.auth_account_client#com.google.android.calendar: pid=4443 uid=10149 user=0 target=e01d2a5
Logs for when it should not be seen as pending (but still seen as pending):
emu64xa:/ $ dumpsys content | grep calendar
JobId=32 [email protected]/com.google u0 [com.android.calendar] PERIODIC Reason=Periodic (period=1d00h00m00s flex=57m36s) Owner={u0a149 com.google.android.calendar [10] [ACTIVE]} [sync_extra_get_settings=true sync_extra_get_recent_notifications=true sync_extra_get_default_notifications=true sync_periodic=true ]
JobId=33 [email protected]/com.google u0 [com.google.android.calendar] PERIODIC Reason=Periodic (period=1d00h00m00s flex=57m36s) Owner={u0a149 com.google.android.calendar [10] [ACTIVE]} [periodic_sync=true run_sync=true ]
JobId=44 [email protected]/com.google u0 [com.google.android.calendar.tasks] PERIODIC Reason=Periodic (period=1d00h00m00s flex=57m36s) Owner={u0a149 com.google.android.calendar [10] [ACTIVE]} [sync_reason=PERIODIC ]
com.android.calendar 1 true Total 64 0 0 3 161 33 261 0 7 1m46s OTHER SUCCESS
com.google.android.calendar 1 true Total 0 0 0 0 0 5 5 0 0 4s OTHER SUCCESS
com.google.android.calendar.tasks 1 true Total 0 0 0 0 0 2 2 0 0 1s OTHER SUCCESS
com.android.calendar 1 true Total 0 0 0 0 0 1 1 0 0 1s OTHER SUCCESS
com.android.calendar : 5/29% 6s/39%
#1 : 2025-05-07 11:58:30 OTHER 1.2s [email protected]/bitfire.at.davdroid u0 com.android.calendar AutoSync
#6 : 2025-05-07 11:57:31 OTHER 0.1s [email protected]/com.google u0 com.android.calendar com.google.android.calendar
#7 : 2025-05-07 11:57:30 OTHER 1.3s 1 [email protected]/com.google u0 com.android.calendar ServiceChanged
#9 : 2025-05-07 11:57:28 OTHER 0.7s 1 [email protected]/com.google u0 com.android.calendar ServiceChanged
#11 : 2025-05-07 11:57:24 OTHER 3.1s 3 [email protected]/com.google u0 com.android.calendar ServiceChanged
#6 : 2025-05-07 11:57:31 OTHER [email protected]/com.google u0 com.android.calendar Bundle[{[email protected]}]
[email protected]/com.google u0 [com.android.calendar]
2025-05-07 11:52:18 success Source=USER Elapsed=0s Reason=10149 Exemption=fg Extras=[ignore_settings=true force=true ignore_backoff=true feed_internal=en.usa#[email protected] ]
2025-05-07 11:52:17 success Source=USER Elapsed=0s Reason=10149 Exemption=fg Extras=[ignore_settings=true force=true ignore_backoff=true feed_internal=de.austrian#[email protected] ]
[email protected]/com.google u0 [com.google.android.calendar]
[email protected]/com.google u0 [com.google.android.calendar.tasks]
[email protected]/bitfire.at.davdroid u0 [com.android.calendar]
ServiceInfo: SyncAdapterType {name=com.google.android.calendar.tasks, type=com.google, userVisible=true, supportsUploading=false, isAlwaysSyncable=false, allowParallelSyncs=true, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.android.apps.calendar.vagabond.tasks.impl.sync.PlatformSync$SyncService}, uid 10149
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=bitfire.at.davdroid, userVisible=false, supportsUploading=true, isAlwaysSyncable=true, allowParallelSyncs=true, settingsActivity=null, packageName=at.bitfire.davdroid}, ComponentInfo{at.bitfire.davdroid/at.bitfire.davdroid.sync.CalendarsSyncAdapterService}, uid 10209
ServiceInfo: SyncAdapterType {name=com.google.android.calendar, type=com.google, userVisible=true, supportsUploading=false, isAlwaysSyncable=false, allowParallelSyncs=true, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.calendar.v2a.shared.sync.impl.android.PlatformSyncShell$SyncAdapterService}, uid 10149
ServiceInfo: SyncAdapterType {name=com.android.calendar, type=com.google, userVisible=true, supportsUploading=true, isAlwaysSyncable=false, allowParallelSyncs=false, settingsActivity=null, packageName=com.google.android.calendar}, ComponentInfo{com.google.android.calendar/com.google.android.syncadapters.calendar.CalendarSyncAdapterService}, uid 10149
com.android.calendar: pid=587 uid=1000 user=0 target=6a76881
com.android.calendar/instances/when: pid=587 uid=1000 user=0 target=c4d6d4f
com.android.calendar/events: pid=587 uid=1000 user=0 target=c4d6d4f
com.android.calendar/calendars: pid=587 uid=1000 user=0 target=c4d6d4f
com.google.android.gms.phenotype/com.google.android.gms.auth_account_client#com.google.android.calendar: pid=3573 uid=10149 user=0 target=520ffc6
I think it might be due to the AutoSync entry
#1 : 2025-05-07 11:58:30 OTHER 1.2s [email protected]/bitfire.at.davdroid u0 com.android.calendar AutoSync
I am not sure how and why, but I'd like to address that in a different PR and will simply use my A13 emulator for now.
~After installing jtxBoard and creating a task in synchronized collection, I observe the same behaviour (forever pending state) on the A13 emulator. It stays even after uninstalling jtxBoard or rebooting the emulator.~
Just interested in the wording: Are "periodic syncs" the same as "pending syncs"? Or can a periodic sync also be a pending sync?
No, they are not the same. A periodic sync runs in intervals and will be "pending" the moment it has been requested/enqueued to run and will then transition to "active" when it actually runs. So "pending" refers to the state a periodic (or manual) sync operation can be in.
Fixed in #1445 for Android <14. For Android >= 14, see #1458.