Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2009 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package android.content; |
| 18 | |
| 19 | import android.accounts.Account; |
| 20 | import android.os.Bundle; |
Fred Quintana | f038004 | 2009-10-06 17:05:58 -0700 | [diff] [blame] | 21 | import android.os.IBinder; |
Ken Shirriff | 1719a39 | 2009-12-07 15:57:35 -0800 | [diff] [blame] | 22 | import android.os.Process; |
Fred Quintana | e7424ff | 2009-10-14 15:59:21 -0700 | [diff] [blame] | 23 | import android.os.RemoteException; |
Andy Stadler | 09b45a3 | 2012-05-03 15:00:49 -0700 | [diff] [blame] | 24 | import android.os.Trace; |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 25 | |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 26 | import java.util.HashMap; |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 27 | import java.util.concurrent.atomic.AtomicInteger; |
| 28 | |
| 29 | /** |
| 30 | * An abstract implementation of a SyncAdapter that spawns a thread to invoke a sync operation. |
Matthew Williams | 1967c8d | 2015-06-19 19:03:13 -0700 | [diff] [blame] | 31 | * If a sync operation is already in progress when a sync request is received, an error will be |
| 32 | * returned to the new request and the existing request will be allowed to continue. |
| 33 | * However if there is no sync in progress then a thread will be spawned and {@link #onPerformSync} |
| 34 | * will be invoked on that thread. |
| 35 | * <p> |
| 36 | * Syncs can be cancelled at any time by the framework. For example a sync that was not |
| 37 | * user-initiated and lasts longer than 30 minutes will be considered timed-out and cancelled. |
| 38 | * Similarly the framework will attempt to determine whether or not an adapter is making progress |
| 39 | * by monitoring its network activity over the course of a minute. If the network traffic over this |
| 40 | * window is close enough to zero the sync will be cancelled. You can also request the sync be |
| 41 | * cancelled via {@link ContentResolver#cancelSync(Account, String)} or |
| 42 | * {@link ContentResolver#cancelSync(SyncRequest)}. |
| 43 | * <p> |
| 44 | * A sync is cancelled by issuing a {@link Thread#interrupt()} on the syncing thread. <strong>Either |
| 45 | * your code in {@link #onPerformSync(Account, Bundle, String, ContentProviderClient, SyncResult)} |
| 46 | * must check {@link Thread#interrupted()}, or you you must override one of |
| 47 | * {@link #onSyncCanceled(Thread)}/{@link #onSyncCanceled()}</strong> (depending on whether or not |
| 48 | * your adapter supports syncing of multiple accounts in parallel). If your adapter does not |
| 49 | * respect the cancel issued by the framework you run the risk of your app's entire process being |
| 50 | * killed. |
Fred Quintana | e6d60ec | 2011-08-24 11:29:00 -0700 | [diff] [blame] | 51 | * <p> |
| 52 | * In order to be a sync adapter one must extend this class, provide implementations for the |
| 53 | * abstract methods and write a service that returns the result of {@link #getSyncAdapterBinder()} |
| 54 | * in the service's {@link android.app.Service#onBind(android.content.Intent)} when invoked |
| 55 | * with an intent with action <code>android.content.SyncAdapter</code>. This service |
| 56 | * must specify the following intent filter and metadata tags in its AndroidManifest.xml file |
| 57 | * <pre> |
| 58 | * <intent-filter> |
| 59 | * <action android:name="android.content.SyncAdapter" /> |
| 60 | * </intent-filter> |
| 61 | * <meta-data android:name="android.content.SyncAdapter" |
| 62 | * android:resource="@xml/syncadapter" /> |
| 63 | * </pre> |
| 64 | * The <code>android:resource</code> attribute must point to a resource that looks like: |
| 65 | * <pre> |
| 66 | * <sync-adapter xmlns:android="http://schemas.android.com/apk/res/android" |
| 67 | * android:contentAuthority="authority" |
| 68 | * android:accountType="accountType" |
| 69 | * android:userVisible="true|false" |
| 70 | * android:supportsUploading="true|false" |
| 71 | * android:allowParallelSyncs="true|false" |
| 72 | * android:isAlwaysSyncable="true|false" |
| 73 | * android:syncAdapterSettingsAction="ACTION_OF_SETTINGS_ACTIVITY" |
| 74 | * /> |
| 75 | * </pre> |
| 76 | * <ul> |
| 77 | * <li>The <code>android:contentAuthority</code> and <code>android:accountType</code> attributes |
| 78 | * indicate which content authority and for which account types this sync adapter serves. |
| 79 | * <li><code>android:userVisible</code> defaults to true and controls whether or not this sync |
| 80 | * adapter shows up in the Sync Settings screen. |
| 81 | * <li><code>android:supportsUploading</code> defaults |
| 82 | * to true and if true an upload-only sync will be requested for all syncadapters associated |
| 83 | * with an authority whenever that authority's content provider does a |
| 84 | * {@link ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver, boolean)} |
| 85 | * with syncToNetwork set to true. |
| 86 | * <li><code>android:allowParallelSyncs</code> defaults to false and if true indicates that |
| 87 | * the sync adapter can handle syncs for multiple accounts at the same time. Otherwise |
| 88 | * the SyncManager will wait until the sync adapter is not in use before requesting that |
| 89 | * it sync an account's data. |
| 90 | * <li><code>android:isAlwaysSyncable</code> defaults to false and if true tells the SyncManager |
| 91 | * to intialize the isSyncable state to 1 for that sync adapter for each account that is added. |
| 92 | * <li><code>android:syncAdapterSettingsAction</code> defaults to null and if supplied it |
| 93 | * specifies an Intent action of an activity that can be used to adjust the sync adapter's |
| 94 | * sync settings. The activity must live in the same package as the sync adapter. |
| 95 | * </ul> |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 96 | */ |
| 97 | public abstract class AbstractThreadedSyncAdapter { |
Fred Quintana | 97ef763 | 2009-12-10 10:33:18 -0800 | [diff] [blame] | 98 | /** |
| 99 | * Kernel event log tag. Also listed in data/etc/event-log-tags. |
Joe Onorato | d3ad696 | 2010-09-16 13:38:25 -0400 | [diff] [blame] | 100 | * @deprecated Private constant. May go away in the next release. |
Fred Quintana | 97ef763 | 2009-12-10 10:33:18 -0800 | [diff] [blame] | 101 | */ |
Joe Onorato | d3ad696 | 2010-09-16 13:38:25 -0400 | [diff] [blame] | 102 | @Deprecated |
Fred Quintana | 97ef763 | 2009-12-10 10:33:18 -0800 | [diff] [blame] | 103 | public static final int LOG_SYNC_DETAILS = 2743; |
| 104 | |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 105 | private final Context mContext; |
| 106 | private final AtomicInteger mNumSyncStarts; |
| 107 | private final ISyncAdapterImpl mISyncAdapterImpl; |
| 108 | |
Fred Quintana | 3cff76a | 2009-08-26 18:49:19 -0700 | [diff] [blame] | 109 | // all accesses to this member variable must be synchronized on mSyncThreadLock |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 110 | private final HashMap<Account, SyncThread> mSyncThreads = new HashMap<Account, SyncThread>(); |
Fred Quintana | 3cff76a | 2009-08-26 18:49:19 -0700 | [diff] [blame] | 111 | private final Object mSyncThreadLock = new Object(); |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 112 | |
Fred Quintana | 4a6679b | 2009-08-17 13:05:39 -0700 | [diff] [blame] | 113 | private final boolean mAutoInitialize; |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 114 | private boolean mAllowParallelSyncs; |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 115 | |
| 116 | /** |
| 117 | * Creates an {@link AbstractThreadedSyncAdapter}. |
Fred Quintana | 4a6679b | 2009-08-17 13:05:39 -0700 | [diff] [blame] | 118 | * @param context the {@link android.content.Context} that this is running within. |
| 119 | * @param autoInitialize if true then sync requests that have |
| 120 | * {@link ContentResolver#SYNC_EXTRAS_INITIALIZE} set will be internally handled by |
| 121 | * {@link AbstractThreadedSyncAdapter} by calling |
| 122 | * {@link ContentResolver#setIsSyncable(android.accounts.Account, String, int)} with 1 if it |
| 123 | * is currently set to <0. |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 124 | */ |
Fred Quintana | 4a6679b | 2009-08-17 13:05:39 -0700 | [diff] [blame] | 125 | public AbstractThreadedSyncAdapter(Context context, boolean autoInitialize) { |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 126 | this(context, autoInitialize, false /* allowParallelSyncs */); |
| 127 | } |
| 128 | |
| 129 | /** |
| 130 | * Creates an {@link AbstractThreadedSyncAdapter}. |
| 131 | * @param context the {@link android.content.Context} that this is running within. |
| 132 | * @param autoInitialize if true then sync requests that have |
| 133 | * {@link ContentResolver#SYNC_EXTRAS_INITIALIZE} set will be internally handled by |
| 134 | * {@link AbstractThreadedSyncAdapter} by calling |
| 135 | * {@link ContentResolver#setIsSyncable(android.accounts.Account, String, int)} with 1 if it |
| 136 | * is currently set to <0. |
| 137 | * @param allowParallelSyncs if true then allow syncs for different accounts to run |
| 138 | * at the same time, each in their own thread. This must be consistent with the setting |
| 139 | * in the SyncAdapter's configuration file. |
| 140 | */ |
| 141 | public AbstractThreadedSyncAdapter(Context context, |
| 142 | boolean autoInitialize, boolean allowParallelSyncs) { |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 143 | mContext = context; |
| 144 | mISyncAdapterImpl = new ISyncAdapterImpl(); |
| 145 | mNumSyncStarts = new AtomicInteger(0); |
Fred Quintana | 4a6679b | 2009-08-17 13:05:39 -0700 | [diff] [blame] | 146 | mAutoInitialize = autoInitialize; |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 147 | mAllowParallelSyncs = allowParallelSyncs; |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 148 | } |
| 149 | |
Fred Quintana | c298a85 | 2009-08-27 18:28:17 -0700 | [diff] [blame] | 150 | public Context getContext() { |
| 151 | return mContext; |
| 152 | } |
| 153 | |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 154 | private Account toSyncKey(Account account) { |
| 155 | if (mAllowParallelSyncs) { |
| 156 | return account; |
| 157 | } else { |
| 158 | return null; |
| 159 | } |
| 160 | } |
| 161 | |
Fred Quintana | f038004 | 2009-10-06 17:05:58 -0700 | [diff] [blame] | 162 | private class ISyncAdapterImpl extends ISyncAdapter.Stub { |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 163 | @Override |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 164 | public void startSync(ISyncContext syncContext, String authority, Account account, |
| 165 | Bundle extras) { |
| 166 | final SyncContext syncContextClient = new SyncContext(syncContext); |
| 167 | |
| 168 | boolean alreadyInProgress; |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 169 | // synchronize to make sure that mSyncThreads doesn't change between when we |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 170 | // check it and when we use it |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 171 | final Account threadsKey = toSyncKey(account); |
Fred Quintana | 3cff76a | 2009-08-26 18:49:19 -0700 | [diff] [blame] | 172 | synchronized (mSyncThreadLock) { |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 173 | if (!mSyncThreads.containsKey(threadsKey)) { |
Fred Quintana | 4a6679b | 2009-08-17 13:05:39 -0700 | [diff] [blame] | 174 | if (mAutoInitialize |
| 175 | && extras != null |
| 176 | && extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)) { |
Daniel Karlberg | 8014cbff | 2012-08-15 10:00:41 +0200 | [diff] [blame] | 177 | try { |
| 178 | if (ContentResolver.getIsSyncable(account, authority) < 0) { |
| 179 | ContentResolver.setIsSyncable(account, authority, 1); |
| 180 | } |
| 181 | } finally { |
| 182 | syncContextClient.onFinished(new SyncResult()); |
Fred Quintana | 4a6679b | 2009-08-17 13:05:39 -0700 | [diff] [blame] | 183 | } |
Fred Quintana | 4a6679b | 2009-08-17 13:05:39 -0700 | [diff] [blame] | 184 | return; |
| 185 | } |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 186 | SyncThread syncThread = new SyncThread( |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 187 | "SyncAdapterThread-" + mNumSyncStarts.incrementAndGet(), |
| 188 | syncContextClient, authority, account, extras); |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 189 | mSyncThreads.put(threadsKey, syncThread); |
| 190 | syncThread.start(); |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 191 | alreadyInProgress = false; |
| 192 | } else { |
| 193 | alreadyInProgress = true; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | // do this outside since we don't want to call back into the syncContext while |
| 198 | // holding the synchronization lock |
| 199 | if (alreadyInProgress) { |
| 200 | syncContextClient.onFinished(SyncResult.ALREADY_IN_PROGRESS); |
| 201 | } |
| 202 | } |
| 203 | |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 204 | @Override |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 205 | public void cancelSync(ISyncContext syncContext) { |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 206 | // synchronize to make sure that mSyncThreads doesn't change between when we |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 207 | // check it and when we use it |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 208 | SyncThread info = null; |
Fred Quintana | 3cff76a | 2009-08-26 18:49:19 -0700 | [diff] [blame] | 209 | synchronized (mSyncThreadLock) { |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 210 | for (SyncThread current : mSyncThreads.values()) { |
| 211 | if (current.mSyncContext.getSyncContextBinder() == syncContext.asBinder()) { |
| 212 | info = current; |
| 213 | break; |
| 214 | } |
| 215 | } |
Fred Quintana | d5e4fdc | 2010-03-30 15:16:21 -0700 | [diff] [blame] | 216 | } |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 217 | if (info != null) { |
| 218 | if (mAllowParallelSyncs) { |
| 219 | onSyncCanceled(info); |
| 220 | } else { |
| 221 | onSyncCanceled(); |
| 222 | } |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 223 | } |
| 224 | } |
Fred Quintana | e7424ff | 2009-10-14 15:59:21 -0700 | [diff] [blame] | 225 | |
| 226 | public void initialize(Account account, String authority) throws RemoteException { |
| 227 | Bundle extras = new Bundle(); |
| 228 | extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true); |
| 229 | startSync(null, authority, account, extras); |
| 230 | } |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | /** |
Fred Quintana | f038004 | 2009-10-06 17:05:58 -0700 | [diff] [blame] | 234 | * The thread that invokes {@link AbstractThreadedSyncAdapter#onPerformSync}. It also acquires |
| 235 | * the provider for this sync before calling onPerformSync and releases it afterwards. Cancel |
| 236 | * this thread in order to cancel the sync. |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 237 | */ |
| 238 | private class SyncThread extends Thread { |
| 239 | private final SyncContext mSyncContext; |
| 240 | private final String mAuthority; |
| 241 | private final Account mAccount; |
| 242 | private final Bundle mExtras; |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 243 | private final Account mThreadsKey; |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 244 | |
| 245 | private SyncThread(String name, SyncContext syncContext, String authority, |
| 246 | Account account, Bundle extras) { |
| 247 | super(name); |
| 248 | mSyncContext = syncContext; |
| 249 | mAuthority = authority; |
| 250 | mAccount = account; |
| 251 | mExtras = extras; |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 252 | mThreadsKey = toSyncKey(account); |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 253 | } |
| 254 | |
Andy Stadler | 09b45a3 | 2012-05-03 15:00:49 -0700 | [diff] [blame] | 255 | @Override |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 256 | public void run() { |
Fred Quintana | 75d797c | 2009-08-25 15:05:02 -0700 | [diff] [blame] | 257 | Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); |
| 258 | |
Andy Stadler | 09b45a3 | 2012-05-03 15:00:49 -0700 | [diff] [blame] | 259 | // Trace this sync instance. Note, conceptually this should be in |
| 260 | // SyncStorageEngine.insertStartSyncEvent(), but the trace functions require unique |
| 261 | // threads in order to track overlapping operations, so we'll do it here for now. |
| 262 | Trace.traceBegin(Trace.TRACE_TAG_SYNC_MANAGER, mAuthority); |
| 263 | |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 264 | SyncResult syncResult = new SyncResult(); |
| 265 | ContentProviderClient provider = null; |
| 266 | try { |
Alon Albert | 9257ec0 | 2011-02-07 10:53:26 -0800 | [diff] [blame] | 267 | if (isCanceled()) { |
| 268 | return; |
| 269 | } |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 270 | provider = mContext.getContentResolver().acquireContentProviderClient(mAuthority); |
| 271 | if (provider != null) { |
Fred Quintana | f038004 | 2009-10-06 17:05:58 -0700 | [diff] [blame] | 272 | AbstractThreadedSyncAdapter.this.onPerformSync(mAccount, mExtras, |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 273 | mAuthority, provider, syncResult); |
| 274 | } else { |
Fred Quintana | f038004 | 2009-10-06 17:05:58 -0700 | [diff] [blame] | 275 | syncResult.databaseError = true; |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 276 | } |
Dianne Hackborn | d01ed46 | 2015-06-22 17:41:44 -0700 | [diff] [blame] | 277 | } catch (SecurityException e) { |
| 278 | AbstractThreadedSyncAdapter.this.onSecurityException(mAccount, mExtras, |
| 279 | mAuthority, syncResult); |
| 280 | syncResult.databaseError = true; |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 281 | } finally { |
Andy Stadler | 09b45a3 | 2012-05-03 15:00:49 -0700 | [diff] [blame] | 282 | Trace.traceEnd(Trace.TRACE_TAG_SYNC_MANAGER); |
| 283 | |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 284 | if (provider != null) { |
| 285 | provider.release(); |
| 286 | } |
| 287 | if (!isCanceled()) { |
| 288 | mSyncContext.onFinished(syncResult); |
| 289 | } |
| 290 | // synchronize so that the assignment will be seen by other threads |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 291 | // that also synchronize accesses to mSyncThreads |
Fred Quintana | 3cff76a | 2009-08-26 18:49:19 -0700 | [diff] [blame] | 292 | synchronized (mSyncThreadLock) { |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 293 | mSyncThreads.remove(mThreadsKey); |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 294 | } |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | private boolean isCanceled() { |
| 299 | return Thread.currentThread().isInterrupted(); |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | /** |
Fred Quintana | f038004 | 2009-10-06 17:05:58 -0700 | [diff] [blame] | 304 | * @return a reference to the IBinder of the SyncAdapter service. |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 305 | */ |
Fred Quintana | f038004 | 2009-10-06 17:05:58 -0700 | [diff] [blame] | 306 | public final IBinder getSyncAdapterBinder() { |
| 307 | return mISyncAdapterImpl.asBinder(); |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 308 | } |
| 309 | |
| 310 | /** |
| 311 | * Perform a sync for this account. SyncAdapter-specific parameters may |
| 312 | * be specified in extras, which is guaranteed to not be null. Invocations |
| 313 | * of this method are guaranteed to be serialized. |
| 314 | * |
| 315 | * @param account the account that should be synced |
| 316 | * @param extras SyncAdapter-specific parameters |
| 317 | * @param authority the authority of this sync request |
| 318 | * @param provider a ContentProviderClient that points to the ContentProvider for this |
| 319 | * authority |
| 320 | * @param syncResult SyncAdapter-specific parameters |
| 321 | */ |
Fred Quintana | f038004 | 2009-10-06 17:05:58 -0700 | [diff] [blame] | 322 | public abstract void onPerformSync(Account account, Bundle extras, |
Fred Quintana | 21bb0de | 2009-06-16 10:24:58 -0700 | [diff] [blame] | 323 | String authority, ContentProviderClient provider, SyncResult syncResult); |
Fred Quintana | 274dc9d | 2009-12-11 13:17:08 -0800 | [diff] [blame] | 324 | |
| 325 | /** |
Dianne Hackborn | d01ed46 | 2015-06-22 17:41:44 -0700 | [diff] [blame] | 326 | * Report that there was a security exception when opening the content provider |
| 327 | * prior to calling {@link #onPerformSync}. This will be treated as a sync |
| 328 | * database failure. |
| 329 | * |
| 330 | * @param account the account that attempted to sync |
| 331 | * @param extras SyncAdapter-specific parameters |
| 332 | * @param authority the authority of the failed sync request |
| 333 | * @param syncResult SyncAdapter-specific parameters |
| 334 | */ |
| 335 | public void onSecurityException(Account account, Bundle extras, |
| 336 | String authority, SyncResult syncResult) { |
| 337 | } |
| 338 | |
| 339 | /** |
Fred Quintana | 274dc9d | 2009-12-11 13:17:08 -0800 | [diff] [blame] | 340 | * Indicates that a sync operation has been canceled. This will be invoked on a separate |
| 341 | * thread than the sync thread and so you must consider the multi-threaded implications |
| 342 | * of the work that you do in this method. |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 343 | * <p> |
| 344 | * This will only be invoked when the SyncAdapter indicates that it doesn't support |
| 345 | * parallel syncs. |
Fred Quintana | 274dc9d | 2009-12-11 13:17:08 -0800 | [diff] [blame] | 346 | */ |
Fred Quintana | d5e4fdc | 2010-03-30 15:16:21 -0700 | [diff] [blame] | 347 | public void onSyncCanceled() { |
| 348 | final SyncThread syncThread; |
| 349 | synchronized (mSyncThreadLock) { |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 350 | syncThread = mSyncThreads.get(null); |
Fred Quintana | d5e4fdc | 2010-03-30 15:16:21 -0700 | [diff] [blame] | 351 | } |
| 352 | if (syncThread != null) { |
| 353 | syncThread.interrupt(); |
| 354 | } |
Fred Quintana | 274dc9d | 2009-12-11 13:17:08 -0800 | [diff] [blame] | 355 | } |
Fred Quintana | 0c4d04a | 2010-11-03 17:02:55 -0700 | [diff] [blame] | 356 | |
| 357 | /** |
| 358 | * Indicates that a sync operation has been canceled. This will be invoked on a separate |
| 359 | * thread than the sync thread and so you must consider the multi-threaded implications |
| 360 | * of the work that you do in this method. |
| 361 | * <p> |
| 362 | * This will only be invoked when the SyncAdapter indicates that it does support |
| 363 | * parallel syncs. |
| 364 | * @param thread the Thread of the sync that is to be canceled. |
| 365 | */ |
| 366 | public void onSyncCanceled(Thread thread) { |
| 367 | thread.interrupt(); |
| 368 | } |
Fred Quintana | f038004 | 2009-10-06 17:05:58 -0700 | [diff] [blame] | 369 | } |