Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package android.content; |
| 18 | |
| 19 | import android.accounts.Account; |
| 20 | import android.os.Bundle; |
| 21 | import android.os.Parcel; |
| 22 | import android.os.Parcelable; |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 23 | |
| 24 | public 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 Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 34 | /** Don't allow this sync request on metered networks. */ |
| 35 | private final boolean mDisallowMetered; |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 36 | /** |
| 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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 47 | * Amount of time before {@link #mSyncRunTimeSecs} from which the sync may optionally be |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 48 | * 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 87 | * |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 88 | * @return account object for this sync. |
| 89 | * @throws IllegalArgumentException if this function is called for a request that targets a |
| 90 | * sync service. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 91 | */ |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 92 | public Account getAccount() { |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 93 | if (!hasAuthority()) { |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 94 | throw new IllegalArgumentException("Cannot getAccount() for a sync that targets a sync" |
| 95 | + "service."); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 96 | } |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 97 | 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 113 | } |
| 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 Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 177 | parcel.writeInt((mDisallowMetered ? 1 : 0)); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 178 | 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 Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 195 | mDisallowMetered = (in.readInt() != 0); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 196 | 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 Williams | 68e39c3 | 2013-07-25 16:40:23 -0700 | [diff] [blame] | 222 | // 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 Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 225 | mDisallowMetered = b.mDisallowMetered; |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 226 | 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 Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 271 | private boolean mDisallowMetered; |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 272 | /** 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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 284 | * periodic syncs. See {@link ContentResolver#SYNC_EXTRAS_DO_NOT_RETRY}. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 285 | */ |
| 286 | private boolean mNoRetry; |
| 287 | /** |
| 288 | * Whether to respect back-off for this one-time sync. Not valid for |
| 289 | * periodic syncs. See |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 290 | * {@link ContentResolver#SYNC_EXTRAS_IGNORE_BACKOFF}; |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 291 | */ |
| 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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 301 | * The {@link SyncService} component that |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 302 | * 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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 308 | * this sync is bound to a provider), otherwise null. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 309 | */ |
| 310 | private Account mAccount; |
| 311 | /** |
| 312 | * The Authority name that together with an Account define the SyncAdapter (if |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 313 | * this sync is bound to a provider), otherwise null. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 314 | */ |
| 315 | private String mAuthority; |
| 316 | |
| 317 | public Builder() { |
| 318 | } |
| 319 | |
| 320 | /** |
Nick Kralevich | 47d2b61 | 2013-10-19 10:43:55 -0700 | [diff] [blame] | 321 | * Request that a sync occur immediately. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 322 | * |
| 323 | * Example |
| 324 | * <pre> |
Nick Kralevich | 69002ae | 2013-10-19 08:43:08 -0700 | [diff] [blame] | 325 | * SyncRequest.Builder builder = (new SyncRequest.Builder()).syncOnce(); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 326 | * </pre> |
| 327 | */ |
Nick Kralevich | 69002ae | 2013-10-19 08:43:08 -0700 | [diff] [blame] | 328 | public Builder syncOnce() { |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 329 | if (mSyncType != SYNC_TYPE_UNKNOWN) { |
| 330 | throw new IllegalArgumentException("Sync type has already been defined."); |
| 331 | } |
| 332 | mSyncType = SYNC_TYPE_ONCE; |
Nick Kralevich | 69002ae | 2013-10-19 08:43:08 -0700 | [diff] [blame] | 333 | setupInterval(0, 0); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 334 | 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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 342 | * sync (by calling this function). If you do, an <code>IllegalArgumentException</code> |
| 343 | * will be thrown. |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 344 | * <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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 348 | * |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 349 | * 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 Wang | 8cf4e13 | 2013-07-24 20:47:19 -0700 | [diff] [blame] | 362 | * {@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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 369 | * set to true. If any are supplied then an <code>IllegalArgumentException</code> will |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 370 | * 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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 391 | " after the specified flex time."); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 392 | } |
| 393 | mSyncRunTimeSecs = at; |
| 394 | mSyncFlexTimeSecs = before; |
| 395 | } |
| 396 | |
| 397 | /** |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 398 | * Developer can provide insight into their payload size; optional. -1 specifies unknown, |
| 399 | * so that you are not restricted to defining both fields. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 400 | * |
| 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 Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 411 | * 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 415 | */ |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 416 | 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 422 | return this; |
| 423 | } |
| 424 | |
| 425 | /** |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 426 | * Specify an authority and account for this transfer. Cannot be used with |
| 427 | * {@link #setSyncAdapter(ComponentName cname)}. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 428 | * |
| 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 Williams | 632515b | 2013-10-10 15:51:00 -0700 | [diff] [blame] | 438 | if (authority != null && authority.length() == 0) { |
| 439 | throw new IllegalArgumentException("Authority must be non-empty"); |
| 440 | } |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 441 | mSyncTarget = SYNC_TARGET_ADAPTER; |
| 442 | mAccount = account; |
| 443 | mAuthority = authority; |
| 444 | mComponentName = null; |
| 445 | return this; |
| 446 | } |
| 447 | |
| 448 | /** |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 449 | * 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 452 | * |
| 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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 468 | * into the SyncRequest returned by {@link #build()}. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 469 | * |
| 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 485 | * 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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 499 | * @param bundle extras bundle to set. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 500 | */ |
| 501 | public Builder setExtras(Bundle bundle) { |
| 502 | mCustomExtras = bundle; |
| 503 | return this; |
| 504 | } |
| 505 | |
| 506 | /** |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 507 | * Convenience function for setting {@link ContentResolver#SYNC_EXTRAS_DO_NOT_RETRY}. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 508 | * |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 509 | * 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 514 | */ |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 515 | public Builder setNoRetry(boolean noRetry) { |
| 516 | mNoRetry = noRetry; |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 517 | return this; |
| 518 | } |
| 519 | |
| 520 | /** |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 521 | * 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 Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 525 | * <p>Throws <code>IllegalArgumentException</code> if called and |
| 526 | * {@link #setDisallowMetered(boolean)} has been set. |
| 527 | * |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 528 | * |
| 529 | * @param ignoreSettings true to ignore the sync automatically settings. Default false. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 530 | */ |
| 531 | public Builder setIgnoreSettings(boolean ignoreSettings) { |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 532 | if (mDisallowMetered && ignoreSettings) { |
| 533 | throw new IllegalArgumentException("setIgnoreSettings(true) after having specified" |
| 534 | + " sync settings with this builder."); |
| 535 | } |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 536 | mIgnoreSettings = ignoreSettings; |
| 537 | return this; |
| 538 | } |
| 539 | |
| 540 | /** |
Ying Wang | 8cf4e13 | 2013-07-24 20:47:19 -0700 | [diff] [blame] | 541 | * Convenience function for setting {@link ContentResolver#SYNC_EXTRAS_IGNORE_BACKOFF}. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 542 | * |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 543 | * 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 550 | */ |
| 551 | public Builder setIgnoreBackoff(boolean ignoreBackoff) { |
| 552 | mIgnoreBackoff = ignoreBackoff; |
| 553 | return this; |
| 554 | } |
| 555 | |
| 556 | /** |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 557 | * 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 563 | */ |
| 564 | public Builder setManual(boolean isManual) { |
| 565 | mIsManual = isManual; |
| 566 | return this; |
| 567 | } |
| 568 | |
| 569 | /** |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 570 | * 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 576 | */ |
| 577 | public Builder setExpedited(boolean expedited) { |
| 578 | mExpedited = expedited; |
| 579 | return this; |
| 580 | } |
| 581 | |
| 582 | /** |
Matthew Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 583 | * @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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 585 | */ |
| 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 Williams | c81891c | 2013-07-24 19:09:30 -0700 | [diff] [blame] | 596 | * <code>IllegalArgumentException</code> if this validation fails. |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 597 | * |
| 598 | * @return a SyncRequest with the information contained within this |
| 599 | * builder. |
| 600 | */ |
| 601 | public SyncRequest build() { |
| 602 | // Validate the extras bundle |
Matthew Williams | 68e39c3 | 2013-07-25 16:40:23 -0700 | [diff] [blame] | 603 | ContentResolver.validateSyncExtrasBundle(mCustomExtras); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 604 | if (mCustomExtras == null) { |
| 605 | mCustomExtras = new Bundle(); |
| 606 | } |
Matthew Williams | 68e39c3 | 2013-07-25 16:40:23 -0700 | [diff] [blame] | 607 | // Combine builder extra flags into the config bundle. |
| 608 | mSyncConfigExtras = new Bundle(); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 609 | if (mIgnoreBackoff) { |
Matthew Williams | 68e39c3 | 2013-07-25 16:40:23 -0700 | [diff] [blame] | 610 | mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 611 | } |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 612 | if (mDisallowMetered) { |
| 613 | mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, true); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 614 | } |
| 615 | if (mIgnoreSettings) { |
Matthew Williams | 68e39c3 | 2013-07-25 16:40:23 -0700 | [diff] [blame] | 616 | mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 617 | } |
| 618 | if (mNoRetry) { |
Matthew Williams | 68e39c3 | 2013-07-25 16:40:23 -0700 | [diff] [blame] | 619 | mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 620 | } |
| 621 | if (mExpedited) { |
Matthew Williams | 68e39c3 | 2013-07-25 16:40:23 -0700 | [diff] [blame] | 622 | mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 623 | } |
| 624 | if (mIsManual) { |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 625 | mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true); |
| 626 | mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true); |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 627 | } |
Matthew Williams | 68e39c3 | 2013-07-25 16:40:23 -0700 | [diff] [blame] | 628 | 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 631 | if (mSyncType == SYNC_TYPE_PERIODIC) { |
Matthew Williams | 68e39c3 | 2013-07-25 16:40:23 -0700 | [diff] [blame] | 632 | // If this is a periodic sync ensure than invalid extras were not set. |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 633 | if (ContentResolver.invalidPeriodicExtras(mCustomExtras) || |
| 634 | ContentResolver.invalidPeriodicExtras(mSyncConfigExtras)) { |
| 635 | throw new IllegalArgumentException("Illegal extras were set"); |
| 636 | } |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 637 | } else if (mSyncType == SYNC_TYPE_UNKNOWN) { |
| 638 | throw new IllegalArgumentException("Must call either syncOnce() or syncPeriodic()"); |
| 639 | } |
Matthew Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 640 | 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 Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 646 | // 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 Williams | 56dbf8f | 2013-07-26 12:56:39 -0700 | [diff] [blame] | 653 | } |
Matthew Williams | fa77418 | 2013-06-18 15:44:11 -0700 | [diff] [blame] | 654 | } |