diff --git a/api/current.txt b/api/current.txt index a538d86648dc0..9cb8d59afa74c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7211,6 +7211,7 @@ package android.content { method public android.content.Context getContext(); method public final android.os.IBinder getSyncAdapterBinder(); method public abstract void onPerformSync(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.ContentProviderClient, android.content.SyncResult); + method public void onSecurityException(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.SyncResult); method public void onSyncCanceled(); method public void onSyncCanceled(java.lang.Thread); field public static final deprecated int LOG_SYNC_DETAILS = 2743; // 0xab7 diff --git a/api/system-current.txt b/api/system-current.txt index 57581e29dcd66..9544f5badf16c 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -7436,6 +7436,7 @@ package android.content { method public android.content.Context getContext(); method public final android.os.IBinder getSyncAdapterBinder(); method public abstract void onPerformSync(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.ContentProviderClient, android.content.SyncResult); + method public void onSecurityException(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.SyncResult); method public void onSyncCanceled(); method public void onSyncCanceled(java.lang.Thread); field public static final deprecated int LOG_SYNC_DETAILS = 2743; // 0xab7 diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java index d4dee5b9bc6ad..58bd5cda825dc 100644 --- a/core/java/android/content/AbstractThreadedSyncAdapter.java +++ b/core/java/android/content/AbstractThreadedSyncAdapter.java @@ -274,6 +274,10 @@ public abstract class AbstractThreadedSyncAdapter { } else { syncResult.databaseError = true; } + } catch (SecurityException e) { + AbstractThreadedSyncAdapter.this.onSecurityException(mAccount, mExtras, + mAuthority, syncResult); + syncResult.databaseError = true; } finally { Trace.traceEnd(Trace.TRACE_TAG_SYNC_MANAGER); @@ -318,6 +322,20 @@ public abstract class AbstractThreadedSyncAdapter { public abstract void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult); + /** + * Report that there was a security exception when opening the content provider + * prior to calling {@link #onPerformSync}. This will be treated as a sync + * database failure. + * + * @param account the account that attempted to sync + * @param extras SyncAdapter-specific parameters + * @param authority the authority of the failed sync request + * @param syncResult SyncAdapter-specific parameters + */ + public void onSecurityException(Account account, Bundle extras, + String authority, SyncResult syncResult) { + } + /** * Indicates that a sync operation has been canceled. This will be invoked on a separate * thread than the sync thread and so you must consider the multi-threaded implications