blob: a9a62a7d2fab4e110627ee60ed14c5218604f7b4 [file] [log] [blame]
Matthew Williamsfa774182013-06-18 15:44:11 -07001/*
2 * Copyright (C) 2013 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
17package android.content;
18
19import android.accounts.Account;
20import android.os.Bundle;
21import android.os.Parcel;
22import android.os.Parcelable;
Matthew Williamsfa774182013-06-18 15:44:11 -070023
24public class SyncRequest implements Parcelable {
25 private static final String TAG = "SyncRequest";
26 /** Account to pass to the sync adapter. Can be null. */
27 private final Account mAccountToSync;
28 /** Authority string that corresponds to a ContentProvider. */
29 private final String mAuthority;
30 /** {@link SyncService} identifier. */
31 private final ComponentName mComponentInfo;
32 /** Bundle containing user info as well as sync settings. */
33 private final Bundle mExtras;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070034 /** Don't allow this sync request on metered networks. */
35 private final boolean mDisallowMetered;
Matthew Williamsfa774182013-06-18 15:44:11 -070036 /**
37 * Anticipated upload size in bytes.
38 * TODO: Not yet used - we put this information into the bundle for simplicity.
39 */
40 private final long mTxBytes;
41 /**
42 * Anticipated download size in bytes.
43 * TODO: Not yet used - we put this information into the bundle.
44 */
45 private final long mRxBytes;
46 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -070047 * Amount of time before {@link #mSyncRunTimeSecs} from which the sync may optionally be
Matthew Williamsfa774182013-06-18 15:44:11 -070048 * started.
49 */
50 private final long mSyncFlexTimeSecs;
51 /**
52 * Specifies a point in the future at which the sync must have been scheduled to run.
53 */
54 private final long mSyncRunTimeSecs;
55 /** Periodic versus one-off. */
56 private final boolean mIsPeriodic;
57 /** Service versus provider. */
58 private final boolean mIsAuthority;
59 /** Sync should be run in lieu of other syncs. */
60 private final boolean mIsExpedited;
61
62 /**
63 * {@hide}
64 * @return whether this sync is periodic or one-time. A Sync Request must be
65 * either one of these or an InvalidStateException will be thrown in
66 * Builder.build().
67 */
68 public boolean isPeriodic() {
69 return mIsPeriodic;
70 }
71
72 public boolean isExpedited() {
73 return mIsExpedited;
74 }
75
76 /**
77 * {@hide}
78 * @return true if this sync uses an account/authority pair, or false if
79 * this is an anonymous sync bound to an @link AnonymousSyncService.
80 */
81 public boolean hasAuthority() {
82 return mIsAuthority;
83 }
84
85 /**
86 * {@hide}
Matthew Williamsfa774182013-06-18 15:44:11 -070087 *
Matthew Williams56dbf8f2013-07-26 12:56:39 -070088 * @return account object for this sync.
89 * @throws IllegalArgumentException if this function is called for a request that targets a
90 * sync service.
Matthew Williamsfa774182013-06-18 15:44:11 -070091 */
Matthew Williams56dbf8f2013-07-26 12:56:39 -070092 public Account getAccount() {
Matthew Williamsfa774182013-06-18 15:44:11 -070093 if (!hasAuthority()) {
Matthew Williams56dbf8f2013-07-26 12:56:39 -070094 throw new IllegalArgumentException("Cannot getAccount() for a sync that targets a sync"
95 + "service.");
Matthew Williamsfa774182013-06-18 15:44:11 -070096 }
Matthew Williams56dbf8f2013-07-26 12:56:39 -070097 return mAccountToSync;
98 }
99
100 /**
101 * {@hide}
102 *
103 * @return provider for this sync.
104 * @throws IllegalArgumentException if this function is called for a request that targets a
105 * sync service.
106 */
107 public String getProvider() {
108 if (!hasAuthority()) {
109 throw new IllegalArgumentException("Cannot getProvider() for a sync that targets a"
110 + "sync service.");
111 }
112 return mAuthority;
Matthew Williamsfa774182013-06-18 15:44:11 -0700113 }
114
115 /**
116 * {@hide}
117 * Throws a runtime IllegalArgumentException if this function is called for a
118 * SyncRequest that is bound to an account/provider.
119 *
120 * @return ComponentName for the service that this sync will bind to.
121 */
122 public ComponentName getService() {
123 if (hasAuthority()) {
124 throw new IllegalArgumentException(
125 "Cannot getAnonymousService() for a sync that has specified a provider.");
126 }
127 return mComponentInfo;
128 }
129
130 /**
131 * {@hide}
132 * Retrieve bundle for this SyncRequest. Will not be null.
133 */
134 public Bundle getBundle() {
135 return mExtras;
136 }
137
138 /**
139 * {@hide}
140 * @return the earliest point in time that this sync can be scheduled.
141 */
142 public long getSyncFlexTime() {
143 return mSyncFlexTimeSecs;
144 }
145 /**
146 * {@hide}
147 * @return the last point in time at which this sync must scheduled.
148 */
149 public long getSyncRunTime() {
150 return mSyncRunTimeSecs;
151 }
152
153 public static final Creator<SyncRequest> CREATOR = new Creator<SyncRequest>() {
154
155 @Override
156 public SyncRequest createFromParcel(Parcel in) {
157 return new SyncRequest(in);
158 }
159
160 @Override
161 public SyncRequest[] newArray(int size) {
162 return new SyncRequest[size];
163 }
164 };
165
166 @Override
167 public int describeContents() {
168 return 0;
169 }
170
171 @Override
172 public void writeToParcel(Parcel parcel, int flags) {
173 parcel.writeBundle(mExtras);
174 parcel.writeLong(mSyncFlexTimeSecs);
175 parcel.writeLong(mSyncRunTimeSecs);
176 parcel.writeInt((mIsPeriodic ? 1 : 0));
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700177 parcel.writeInt((mDisallowMetered ? 1 : 0));
Matthew Williamsfa774182013-06-18 15:44:11 -0700178 parcel.writeLong(mTxBytes);
179 parcel.writeLong(mRxBytes);
180 parcel.writeInt((mIsAuthority ? 1 : 0));
181 parcel.writeInt((mIsExpedited? 1 : 0));
182 if (mIsAuthority) {
183 parcel.writeParcelable(mAccountToSync, flags);
184 parcel.writeString(mAuthority);
185 } else {
186 parcel.writeParcelable(mComponentInfo, flags);
187 }
188 }
189
190 private SyncRequest(Parcel in) {
191 mExtras = in.readBundle();
192 mSyncFlexTimeSecs = in.readLong();
193 mSyncRunTimeSecs = in.readLong();
194 mIsPeriodic = (in.readInt() != 0);
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700195 mDisallowMetered = (in.readInt() != 0);
Matthew Williamsfa774182013-06-18 15:44:11 -0700196 mTxBytes = in.readLong();
197 mRxBytes = in.readLong();
198 mIsAuthority = (in.readInt() != 0);
199 mIsExpedited = (in.readInt() != 0);
200 if (mIsAuthority) {
201 mComponentInfo = null;
202 mAccountToSync = in.readParcelable(null);
203 mAuthority = in.readString();
204 } else {
205 mComponentInfo = in.readParcelable(null);
206 mAccountToSync = null;
207 mAuthority = null;
208 }
209 }
210
211 /** {@hide} Protected ctor to instantiate anonymous SyncRequest. */
212 protected SyncRequest(SyncRequest.Builder b) {
213 mSyncFlexTimeSecs = b.mSyncFlexTimeSecs;
214 mSyncRunTimeSecs = b.mSyncRunTimeSecs;
215 mAccountToSync = b.mAccount;
216 mAuthority = b.mAuthority;
217 mComponentInfo = b.mComponentName;
218 mIsPeriodic = (b.mSyncType == Builder.SYNC_TYPE_PERIODIC);
219 mIsAuthority = (b.mSyncTarget == Builder.SYNC_TARGET_ADAPTER);
220 mIsExpedited = b.mExpedited;
221 mExtras = new Bundle(b.mCustomExtras);
Matthew Williams68e39c32013-07-25 16:40:23 -0700222 // For now we merge the sync config extras & the custom extras into one bundle.
223 // TODO: pass the configuration extras through separately.
224 mExtras.putAll(b.mSyncConfigExtras);
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700225 mDisallowMetered = b.mDisallowMetered;
Matthew Williamsfa774182013-06-18 15:44:11 -0700226 mTxBytes = b.mTxBytes;
227 mRxBytes = b.mRxBytes;
228 }
229
230 /**
231 * Builder class for a @link SyncRequest. As you build your SyncRequest this class will also
232 * perform validation.
233 */
234 public static class Builder {
235 /** Unknown sync type. */
236 private static final int SYNC_TYPE_UNKNOWN = 0;
237 /** Specify that this is a periodic sync. */
238 private static final int SYNC_TYPE_PERIODIC = 1;
239 /** Specify that this is a one-time sync. */
240 private static final int SYNC_TYPE_ONCE = 2;
241 /** Unknown sync target. */
242 private static final int SYNC_TARGET_UNKNOWN = 0;
243 /** Specify that this is an anonymous sync. */
244 private static final int SYNC_TARGET_SERVICE = 1;
245 /** Specify that this is a sync with a provider. */
246 private static final int SYNC_TARGET_ADAPTER = 2;
247 /**
248 * Earliest point of displacement into the future at which this sync can
249 * occur.
250 */
251 private long mSyncFlexTimeSecs;
252 /** Displacement into the future at which this sync must occur. */
253 private long mSyncRunTimeSecs;
254 /**
255 * Sync configuration information - custom user data explicitly provided by the developer.
256 * This data is handed over to the sync operation.
257 */
258 private Bundle mCustomExtras;
259 /**
260 * Sync system configuration - used to store system sync configuration. Corresponds to
261 * ContentResolver.SYNC_EXTRAS_* flags.
262 * TODO: Use this instead of dumping into one bundle. Need to decide if these flags should
263 * discriminate between equivalent syncs.
264 */
265 private Bundle mSyncConfigExtras;
266 /** Expected upload transfer in bytes. */
267 private long mTxBytes = -1L;
268 /** Expected download transfer in bytes. */
269 private long mRxBytes = -1L;
270 /** Whether or not this sync can occur on metered networks. Default false. */
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700271 private boolean mDisallowMetered;
Matthew Williamsfa774182013-06-18 15:44:11 -0700272 /** Priority of this sync relative to others from calling app [-2, 2]. Default 0. */
273 private int mPriority = 0;
274 /**
275 * Whether this builder is building a periodic sync, or a one-time sync.
276 */
277 private int mSyncType = SYNC_TYPE_UNKNOWN;
278 /** Whether this will go to a sync adapter or to a sync service. */
279 private int mSyncTarget = SYNC_TARGET_UNKNOWN;
280 /** Whether this is a user-activated sync. */
281 private boolean mIsManual;
282 /**
283 * Whether to retry this one-time sync if the sync fails. Not valid for
Matthew Williamsc81891c2013-07-24 19:09:30 -0700284 * periodic syncs. See {@link ContentResolver#SYNC_EXTRAS_DO_NOT_RETRY}.
Matthew Williamsfa774182013-06-18 15:44:11 -0700285 */
286 private boolean mNoRetry;
287 /**
288 * Whether to respect back-off for this one-time sync. Not valid for
289 * periodic syncs. See
Matthew Williamsc81891c2013-07-24 19:09:30 -0700290 * {@link ContentResolver#SYNC_EXTRAS_IGNORE_BACKOFF};
Matthew Williamsfa774182013-06-18 15:44:11 -0700291 */
292 private boolean mIgnoreBackoff;
293
294 /** Ignore sync system settings and perform sync anyway. */
295 private boolean mIgnoreSettings;
296
297 /** This sync will run in preference to other non-expedited syncs. */
298 private boolean mExpedited;
299
300 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -0700301 * The {@link SyncService} component that
Matthew Williamsfa774182013-06-18 15:44:11 -0700302 * contains the sync logic if this is a provider-less sync, otherwise
303 * null.
304 */
305 private ComponentName mComponentName;
306 /**
307 * The Account object that together with an Authority name define the SyncAdapter (if
Matthew Williamsc81891c2013-07-24 19:09:30 -0700308 * this sync is bound to a provider), otherwise null.
Matthew Williamsfa774182013-06-18 15:44:11 -0700309 */
310 private Account mAccount;
311 /**
312 * The Authority name that together with an Account define the SyncAdapter (if
Matthew Williamsc81891c2013-07-24 19:09:30 -0700313 * this sync is bound to a provider), otherwise null.
Matthew Williamsfa774182013-06-18 15:44:11 -0700314 */
315 private String mAuthority;
316
317 public Builder() {
318 }
319
320 /**
Nick Kralevich47d2b612013-10-19 10:43:55 -0700321 * Request that a sync occur immediately.
Matthew Williamsfa774182013-06-18 15:44:11 -0700322 *
323 * Example
324 * <pre>
Nick Kralevich69002ae2013-10-19 08:43:08 -0700325 * SyncRequest.Builder builder = (new SyncRequest.Builder()).syncOnce();
Matthew Williamsfa774182013-06-18 15:44:11 -0700326 * </pre>
327 */
Nick Kralevich69002ae2013-10-19 08:43:08 -0700328 public Builder syncOnce() {
Matthew Williamsfa774182013-06-18 15:44:11 -0700329 if (mSyncType != SYNC_TYPE_UNKNOWN) {
330 throw new IllegalArgumentException("Sync type has already been defined.");
331 }
332 mSyncType = SYNC_TYPE_ONCE;
Nick Kralevich69002ae2013-10-19 08:43:08 -0700333 setupInterval(0, 0);
Matthew Williamsfa774182013-06-18 15:44:11 -0700334 return this;
335 }
336
337 /**
338 * Build a periodic sync. Either this or syncOnce() <b>must</b> be called for this builder.
339 * Syncs are identified by target {@link SyncService}/{@link android.provider} and by the
340 * contents of the extras bundle.
341 * You cannot reuse the same builder for one-time syncs after having specified a periodic
Matthew Williamsc81891c2013-07-24 19:09:30 -0700342 * sync (by calling this function). If you do, an <code>IllegalArgumentException</code>
343 * will be thrown.
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700344 * <p>The bundle for a periodic sync can be queried by applications with the correct
345 * permissions using
346 * {@link ContentResolver#getPeriodicSyncs(Account account, String provider)}, so no
347 * sensitive data should be transferred here.
Matthew Williamsc81891c2013-07-24 19:09:30 -0700348 *
Matthew Williamsfa774182013-06-18 15:44:11 -0700349 * Example usage.
350 *
351 * <pre>
352 * Request a periodic sync every 5 hours with 20 minutes of flex.
353 * SyncRequest.Builder builder =
354 * (new SyncRequest.Builder()).syncPeriodic(5 * HOUR_IN_SECS, 20 * MIN_IN_SECS);
355 *
356 * Schedule a periodic sync every hour at any point in time during that hour.
357 * SyncRequest.Builder builder =
358 * (new SyncRequest.Builder()).syncPeriodic(1 * HOUR_IN_SECS, 1 * HOUR_IN_SECS);
359 * </pre>
360 *
361 * N.B.: Periodic syncs are not allowed to have any of
Ying Wang8cf4e132013-07-24 20:47:19 -0700362 * {@link ContentResolver#SYNC_EXTRAS_DO_NOT_RETRY},
363 * {@link ContentResolver#SYNC_EXTRAS_IGNORE_BACKOFF},
364 * {@link ContentResolver#SYNC_EXTRAS_IGNORE_SETTINGS},
365 * {@link ContentResolver#SYNC_EXTRAS_INITIALIZE},
366 * {@link ContentResolver#SYNC_EXTRAS_FORCE},
367 * {@link ContentResolver#SYNC_EXTRAS_EXPEDITED},
368 * {@link ContentResolver#SYNC_EXTRAS_MANUAL}
Matthew Williamsc81891c2013-07-24 19:09:30 -0700369 * set to true. If any are supplied then an <code>IllegalArgumentException</code> will
Matthew Williamsfa774182013-06-18 15:44:11 -0700370 * be thrown.
371 *
372 * @param pollFrequency the amount of time in seconds that you wish
373 * to elapse between periodic syncs.
374 * @param beforeSeconds the amount of flex time in seconds before
375 * {@code pollFrequency} that you permit for the sync to take
376 * place. Must be less than {@code pollFrequency}.
377 */
378 public Builder syncPeriodic(long pollFrequency, long beforeSeconds) {
379 if (mSyncType != SYNC_TYPE_UNKNOWN) {
380 throw new IllegalArgumentException("Sync type has already been defined.");
381 }
382 mSyncType = SYNC_TYPE_PERIODIC;
383 setupInterval(pollFrequency, beforeSeconds);
384 return this;
385 }
386
387 /** {@hide} */
388 private void setupInterval(long at, long before) {
389 if (before > at) {
390 throw new IllegalArgumentException("Specified run time for the sync must be" +
Matthew Williamsc81891c2013-07-24 19:09:30 -0700391 " after the specified flex time.");
Matthew Williamsfa774182013-06-18 15:44:11 -0700392 }
393 mSyncRunTimeSecs = at;
394 mSyncFlexTimeSecs = before;
395 }
396
397 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -0700398 * Developer can provide insight into their payload size; optional. -1 specifies unknown,
399 * so that you are not restricted to defining both fields.
Matthew Williamsfa774182013-06-18 15:44:11 -0700400 *
401 * @param rxBytes Bytes expected to be downloaded.
402 * @param txBytes Bytes expected to be uploaded.
403 */
404 public Builder setTransferSize(long rxBytes, long txBytes) {
405 mRxBytes = rxBytes;
406 mTxBytes = txBytes;
407 return this;
408 }
409
410 /**
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700411 * Will throw an <code>IllegalArgumentException</code> if called and
412 * {@link #setIgnoreSettings(boolean ignoreSettings)} has already been called.
413 * @param disallow true to allow this transfer on metered networks. Default false.
414 *
Matthew Williamsfa774182013-06-18 15:44:11 -0700415 */
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700416 public Builder setDisallowMetered(boolean disallow) {
417 if (mIgnoreSettings && disallow) {
418 throw new IllegalArgumentException("setDisallowMetered(true) after having"
419 + "specified that settings are ignored.");
420 }
421 mDisallowMetered = disallow;
Matthew Williamsfa774182013-06-18 15:44:11 -0700422 return this;
423 }
424
425 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -0700426 * Specify an authority and account for this transfer. Cannot be used with
427 * {@link #setSyncAdapter(ComponentName cname)}.
Matthew Williamsfa774182013-06-18 15:44:11 -0700428 *
429 * @param authority
430 * @param account Account to sync. Can be null unless this is a periodic
431 * sync, for which verification by the ContentResolver will
432 * fail. If a sync is performed without an account, the
433 */
434 public Builder setSyncAdapter(Account account, String authority) {
435 if (mSyncTarget != SYNC_TARGET_UNKNOWN) {
436 throw new IllegalArgumentException("Sync target has already been defined.");
437 }
Matthew Williams632515b2013-10-10 15:51:00 -0700438 if (authority != null && authority.length() == 0) {
439 throw new IllegalArgumentException("Authority must be non-empty");
440 }
Matthew Williamsfa774182013-06-18 15:44:11 -0700441 mSyncTarget = SYNC_TARGET_ADAPTER;
442 mAccount = account;
443 mAuthority = authority;
444 mComponentName = null;
445 return this;
446 }
447
448 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -0700449 * Specify the {@link SyncService} component for this sync. This is not validated until
450 * sync time so providing an incorrect component name here will not fail. Cannot be used
451 * with {@link #setSyncAdapter(Account account, String authority)}.
Matthew Williamsfa774182013-06-18 15:44:11 -0700452 *
453 * @param cname ComponentName to identify your Anonymous service
454 */
455 public Builder setSyncAdapter(ComponentName cname) {
456 if (mSyncTarget != SYNC_TARGET_UNKNOWN) {
457 throw new IllegalArgumentException("Sync target has already been defined.");
458 }
459 mSyncTarget = SYNC_TARGET_SERVICE;
460 mComponentName = cname;
461 mAccount = null;
462 mAuthority = null;
463 return this;
464 }
465
466 /**
467 * Developer-provided extras handed back when sync actually occurs. This bundle is copied
Matthew Williamsc81891c2013-07-24 19:09:30 -0700468 * into the SyncRequest returned by {@link #build()}.
Matthew Williamsfa774182013-06-18 15:44:11 -0700469 *
470 * Example:
471 * <pre>
472 * String[] syncItems = {"dog", "cat", "frog", "child"};
473 * SyncRequest.Builder builder =
474 * new SyncRequest.Builder()
475 * .setSyncAdapter(dummyAccount, dummyProvider)
476 * .syncOnce(5 * MINUTES_IN_SECS);
477 *
478 * for (String syncData : syncItems) {
479 * Bundle extras = new Bundle();
480 * extras.setString("data", syncData);
481 * builder.setExtras(extras);
482 * ContentResolver.sync(builder.build()); // Each sync() request creates a unique sync.
483 * }
484 * </pre>
Matthew Williamsfa774182013-06-18 15:44:11 -0700485 * Only values of the following types may be used in the extras bundle:
486 * <ul>
487 * <li>Integer</li>
488 * <li>Long</li>
489 * <li>Boolean</li>
490 * <li>Float</li>
491 * <li>Double</li>
492 * <li>String</li>
493 * <li>Account</li>
494 * <li>null</li>
495 * </ul>
496 * If any data is present in the bundle not of this type, build() will
497 * throw a runtime exception.
498 *
Matthew Williamsc81891c2013-07-24 19:09:30 -0700499 * @param bundle extras bundle to set.
Matthew Williamsfa774182013-06-18 15:44:11 -0700500 */
501 public Builder setExtras(Bundle bundle) {
502 mCustomExtras = bundle;
503 return this;
504 }
505
506 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -0700507 * Convenience function for setting {@link ContentResolver#SYNC_EXTRAS_DO_NOT_RETRY}.
Matthew Williamsfa774182013-06-18 15:44:11 -0700508 *
Matthew Williamsc81891c2013-07-24 19:09:30 -0700509 * A one-off sync operation that fails will be retried with exponential back-off unless
510 * this is set to false. Not valid for periodic sync and will throw an
511 * <code>IllegalArgumentException</code> in build().
512 *
513 * @param noRetry true to not retry a failed sync. Default false.
Matthew Williamsfa774182013-06-18 15:44:11 -0700514 */
Matthew Williamsc81891c2013-07-24 19:09:30 -0700515 public Builder setNoRetry(boolean noRetry) {
516 mNoRetry = noRetry;
Matthew Williamsfa774182013-06-18 15:44:11 -0700517 return this;
518 }
519
520 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -0700521 * Convenience function for setting {@link ContentResolver#SYNC_EXTRAS_IGNORE_SETTINGS}.
522 *
523 * Not valid for periodic sync and will throw an <code>IllegalArgumentException</code> in
524 * {@link #build()}.
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700525 * <p>Throws <code>IllegalArgumentException</code> if called and
526 * {@link #setDisallowMetered(boolean)} has been set.
527 *
Matthew Williamsc81891c2013-07-24 19:09:30 -0700528 *
529 * @param ignoreSettings true to ignore the sync automatically settings. Default false.
Matthew Williamsfa774182013-06-18 15:44:11 -0700530 */
531 public Builder setIgnoreSettings(boolean ignoreSettings) {
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700532 if (mDisallowMetered && ignoreSettings) {
533 throw new IllegalArgumentException("setIgnoreSettings(true) after having specified"
534 + " sync settings with this builder.");
535 }
Matthew Williamsfa774182013-06-18 15:44:11 -0700536 mIgnoreSettings = ignoreSettings;
537 return this;
538 }
539
540 /**
Ying Wang8cf4e132013-07-24 20:47:19 -0700541 * Convenience function for setting {@link ContentResolver#SYNC_EXTRAS_IGNORE_BACKOFF}.
Matthew Williamsfa774182013-06-18 15:44:11 -0700542 *
Matthew Williamsc81891c2013-07-24 19:09:30 -0700543 * Ignoring back-off will force the sync scheduling process to ignore any back-off that was
544 * the result of a failed sync, as well as to invalidate any {@link SyncResult#delayUntil}
545 * value that may have been set by the adapter. Successive failures will not honor this
546 * flag. Not valid for periodic sync and will throw an <code>IllegalArgumentException</code>
547 * in {@link #build()}.
548 *
549 * @param ignoreBackoff ignore back off settings. Default false.
Matthew Williamsfa774182013-06-18 15:44:11 -0700550 */
551 public Builder setIgnoreBackoff(boolean ignoreBackoff) {
552 mIgnoreBackoff = ignoreBackoff;
553 return this;
554 }
555
556 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -0700557 * Convenience function for setting {@link ContentResolver#SYNC_EXTRAS_MANUAL}.
558 *
559 * Not valid for periodic sync and will throw an <code>IllegalArgumentException</code> in
560 * {@link #build()}.
561 *
562 * @param isManual User-initiated sync or not. Default false.
Matthew Williamsfa774182013-06-18 15:44:11 -0700563 */
564 public Builder setManual(boolean isManual) {
565 mIsManual = isManual;
566 return this;
567 }
568
569 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -0700570 * An expedited sync runs immediately and can preempt other non-expedited running syncs.
571 *
572 * Not valid for periodic sync and will throw an <code>IllegalArgumentException</code> in
573 * {@link #build()}.
574 *
575 * @param expedited whether to run expedited. Default false.
Matthew Williamsfa774182013-06-18 15:44:11 -0700576 */
577 public Builder setExpedited(boolean expedited) {
578 mExpedited = expedited;
579 return this;
580 }
581
582 /**
Matthew Williamsc81891c2013-07-24 19:09:30 -0700583 * @param priority the priority of this request among all requests from the calling app.
584 * Range of [-2,2] similar to how this is done with notifications.
Matthew Williamsfa774182013-06-18 15:44:11 -0700585 */
586 public Builder setPriority(int priority) {
587 if (priority < -2 || priority > 2) {
588 throw new IllegalArgumentException("Priority must be within range [-2, 2]");
589 }
590 mPriority = priority;
591 return this;
592 }
593
594 /**
595 * Performs validation over the request and throws the runtime exception
Matthew Williamsc81891c2013-07-24 19:09:30 -0700596 * <code>IllegalArgumentException</code> if this validation fails.
Matthew Williamsfa774182013-06-18 15:44:11 -0700597 *
598 * @return a SyncRequest with the information contained within this
599 * builder.
600 */
601 public SyncRequest build() {
602 // Validate the extras bundle
Matthew Williams68e39c32013-07-25 16:40:23 -0700603 ContentResolver.validateSyncExtrasBundle(mCustomExtras);
Matthew Williamsfa774182013-06-18 15:44:11 -0700604 if (mCustomExtras == null) {
605 mCustomExtras = new Bundle();
606 }
Matthew Williams68e39c32013-07-25 16:40:23 -0700607 // Combine builder extra flags into the config bundle.
608 mSyncConfigExtras = new Bundle();
Matthew Williamsfa774182013-06-18 15:44:11 -0700609 if (mIgnoreBackoff) {
Matthew Williams68e39c32013-07-25 16:40:23 -0700610 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true);
Matthew Williamsfa774182013-06-18 15:44:11 -0700611 }
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700612 if (mDisallowMetered) {
613 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, true);
Matthew Williamsfa774182013-06-18 15:44:11 -0700614 }
615 if (mIgnoreSettings) {
Matthew Williams68e39c32013-07-25 16:40:23 -0700616 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
Matthew Williamsfa774182013-06-18 15:44:11 -0700617 }
618 if (mNoRetry) {
Matthew Williams68e39c32013-07-25 16:40:23 -0700619 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
Matthew Williamsfa774182013-06-18 15:44:11 -0700620 }
621 if (mExpedited) {
Matthew Williams68e39c32013-07-25 16:40:23 -0700622 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
Matthew Williamsfa774182013-06-18 15:44:11 -0700623 }
624 if (mIsManual) {
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700625 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true);
626 mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
Matthew Williamsfa774182013-06-18 15:44:11 -0700627 }
Matthew Williams68e39c32013-07-25 16:40:23 -0700628 mSyncConfigExtras.putLong(ContentResolver.SYNC_EXTRAS_EXPECTED_UPLOAD, mTxBytes);
629 mSyncConfigExtras.putLong(ContentResolver.SYNC_EXTRAS_EXPECTED_DOWNLOAD, mRxBytes);
630 mSyncConfigExtras.putInt(ContentResolver.SYNC_EXTRAS_PRIORITY, mPriority);
Matthew Williamsfa774182013-06-18 15:44:11 -0700631 if (mSyncType == SYNC_TYPE_PERIODIC) {
Matthew Williams68e39c32013-07-25 16:40:23 -0700632 // If this is a periodic sync ensure than invalid extras were not set.
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700633 if (ContentResolver.invalidPeriodicExtras(mCustomExtras) ||
634 ContentResolver.invalidPeriodicExtras(mSyncConfigExtras)) {
635 throw new IllegalArgumentException("Illegal extras were set");
636 }
Matthew Williamsfa774182013-06-18 15:44:11 -0700637 } else if (mSyncType == SYNC_TYPE_UNKNOWN) {
638 throw new IllegalArgumentException("Must call either syncOnce() or syncPeriodic()");
639 }
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700640 if (mSyncTarget == SYNC_TARGET_SERVICE) {
641 if (mSyncConfigExtras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)) {
642 throw new IllegalArgumentException("Cannot specify an initialisation sync"
643 + " that targets a service.");
644 }
645 }
Matthew Williamsfa774182013-06-18 15:44:11 -0700646 // Ensure that a target for the sync has been set.
647 if (mSyncTarget == SYNC_TARGET_UNKNOWN) {
648 throw new IllegalArgumentException("Must specify an adapter with one of"
649 + "setSyncAdapter(ComponentName) or setSyncAdapter(Account, String");
650 }
651 return new SyncRequest(this);
652 }
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700653 }
Matthew Williamsfa774182013-06-18 15:44:11 -0700654}