BatchOperation.commit() is documented to @throws RemoteException on calendar/task/contacts provider errors, and most callers wrap it correctly:
try {
...
batch.commit()
...
} catch (e: RemoteException) {
throw LocalStorageException("...", e)
}
However, several synctools call sites call batch.commit() without any surrounding try/catch, so a raw android.os.RemoteException (or its subclass DeadObjectException, thrown when the content provider process is dead/cached) can propagate un-wrapped up to SyncManager's exception handling.
Unwrapped call sites found so far:
AndroidContact.add()
AndroidContact.update()
AndroidCalendar's orphaned-exception cleanup
AndroidRecurringCalendar's exception-instance helper
AndroidRecurringCalendar's exception-instance helper
DmfsRecurringTaskList's exception-instance helper
DmfsRecurringTaskList's exception-instance helper
JtxRecurringCollection's exception-instance helper
JtxRecurringCollection's exception-instance helper
Consequence
SyncExceptionHandler.classifySyncException() has a special case that rethrows a LocalStorageException whose cause is DeadObjectException, so the sync gets rescheduled as a soft/cached-process condition instead of being shown to the user as an error. That special case only matches when the DeadObjectException is wrapped as documented above.
When all call sites are updated, we can also remove handling the RemoteException in SyncManager's error handling.
BatchOperation.commit()is documented to@throws RemoteExceptionon calendar/task/contacts provider errors, and most callers wrap it correctly:However, several
synctoolscall sites callbatch.commit()without any surroundingtry/catch, so a rawandroid.os.RemoteException(or its subclassDeadObjectException, thrown when the content provider process is dead/cached) can propagate un-wrapped up toSyncManager's exception handling.Unwrapped call sites found so far:
AndroidContact.add()AndroidContact.update()AndroidCalendar's orphaned-exception cleanupAndroidRecurringCalendar's exception-instance helperAndroidRecurringCalendar's exception-instance helperDmfsRecurringTaskList's exception-instance helperDmfsRecurringTaskList's exception-instance helperJtxRecurringCollection's exception-instance helperJtxRecurringCollection's exception-instance helperConsequence
SyncExceptionHandler.classifySyncException()has a special case that rethrows aLocalStorageExceptionwhose cause isDeadObjectException, so the sync gets rescheduled as a soft/cached-process condition instead of being shown to the user as an error. That special case only matches when theDeadObjectExceptionis wrapped as documented above.When all call sites are updated, we can also remove handling the
RemoteExceptionin SyncManager's error handling.