Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How long do bundles get persisted by SyncManager?

I have an application with a SyncAdapter. Additionally to the normal synchronization I trigger a USER_READ event with which I just pass a Bundle to the adapter without persisting it:

Bundle settingsBundle = new Bundle();
settingsBundle.putString(SyncAdapter.USER_READ, uid);
ContentResolver.requestSync(account, authority, settingsBundle);

This will correctly call my synchronization routine sometime in the future. Every uid set in the Bundle will trigger its own run and everything gets synced as expected.

If now the connection is bad, or the request times out, then I set a soft error:

syncResult.stats.numIoExceptions += 1;

which will cause the request to be repeated later. This also works just fine.


How long do these SyncRequests / Bundles get persisted?

The documentation states, that encountering a soft error will cause an exponentional backoff and that the sync will be run some time later.

  • Will it be canceled at some point? After multiple soft errors?
  • Will it be enqueued again after a reboot of the device?

Given the connection is bad and the synchronization fails multiple times with soft errors: I would like to know if just enqueuing a sync request is enough, or if I have to provide some sort of persistence myself to ensure requests being sent at some point.

like image 362
David Medenjak Avatar asked Feb 09 '16 09:02

David Medenjak


1 Answers

I had to dig in Android runtime source a little to find an answer to your question. Let's start from the first part of the question.

Will it [sync] be canceled at some point? After multiple soft errors?

And the answer is probably no, until one of the following conditions is met:

  • sync is cancelled
  • you ask SyncManager not to reschedule sync by starting SyncAdapter with ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY
  • you set SyncResult.tooManyRetries to true and sync isn't upload-only
  • you set SyncResult.tooManyDeletions to true, don't set SyncStats.numInserts or SyncStats.numUpdates to non-null values, and sync isn't upload-only
  • sync has no soft errors but has some hard errors, and it's not upload-only
  • sync runs for more than 30 minutes
  • sync doesn't use network for more than 1 minute

So multiple soft errors don't cancel sync and here's why.

Handling all sync events starts in SyncManager.SyncHandler.handleMessage() method and continues in SyncManager.runSyncFinishedOrCanceledH() method. The first argument of runSyncFinishedOrCanceledH() is SyncResult, which can be null. It's not null either when sync is finished or when SyncAdapter service is disconnected, which is a soft error. And it's null when sync is cancelled, expired (runs more than 30 minutes), not using network for more than 1 minute, and in another case I don't fully understand.

In case SyncResult is not null and sync finished with errors, SyncManager tries to reschedule sync by calling maybeRescheduleSync(). This methods checks some flags and sync results, like ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY and SyncResult.tooManyRetries do decide if it needs to reschedule sync. And after SyncManager checks that sync finished with a soft error syncResult.hasSoftError() it reschedules sync without any additional checks.

And now the second part of the question.

Will it [sync] be enqueued again after a reboot of the device?

Yes, it will. When SystemServer initializes, it creates ContentService and then calls its systemReady() method, which in its turn creates SyncManager. SyncManager in its constructor creates SyncStorageEngine, which reads all pending operations in its constructor including extra bundles. That's why a set of types allowed in sync bundles is very limited. And when user is starting all pending operations are added to SynqQueue by calling SyncQueue.addPendingOperations().

This answer is the result of my analysis of Android code so I cannot guarantee it's 100% correct. But you can use this information as a starting point for your own research.

like image 188
Michael Avatar answered Nov 15 '22 18:11

Michael