diff options
author | Matthew Williams <mjwilliams@google.com> | 2013-08-20 15:32:20 -0700 |
---|---|---|
committer | Matthew Williams <mjwilliams@google.com> | 2013-08-30 21:28:53 +0000 |
commit | 6222288bfbae46550b4914ef1eb12c69dc1f716c (patch) | |
tree | aaba6a3c0cf4ad8fee6b6e19522520dcf8b01ae6 | |
parent | 4b2993123bf9a1c56d0a16b032612834dd418520 (diff) | |
download | frameworks_base-6222288bfbae46550b4914ef1eb12c69dc1f716c.zip frameworks_base-6222288bfbae46550b4914ef1eb12c69dc1f716c.tar.gz frameworks_base-6222288bfbae46550b4914ef1eb12c69dc1f716c.tar.bz2 |
DO NOT MERGE. Remove service component for KLP.
1) As discussed, lack of internal clients -> remove SyncService
component from KLP. This CL reverts that addition.
2) Also includes javadoc cleanup of existing API.
3) Fix naming of allowMetered() -> disallowMetered() in API
4) Removed one-off sync in the future, as it doesn't make sense
for sync adapters.
Change-Id: I1b17094e6edafb2955cdfb99f39b44274fbe86f9
-rw-r--r-- | api/current.txt | 17 | ||||
-rw-r--r-- | core/java/android/content/ContentResolver.java | 26 | ||||
-rw-r--r-- | core/java/android/content/PeriodicSync.java | 71 | ||||
-rw-r--r-- | core/java/android/content/SyncRequest.java | 193 | ||||
-rw-r--r-- | core/java/android/content/SyncService.java | 169 | ||||
-rw-r--r-- | services/java/com/android/server/content/ContentService.java | 20 | ||||
-rw-r--r-- | services/java/com/android/server/content/SyncManager.java | 189 | ||||
-rw-r--r-- | services/java/com/android/server/content/SyncOperation.java | 40 | ||||
-rw-r--r-- | services/java/com/android/server/content/SyncStorageEngine.java | 2 |
9 files changed, 124 insertions, 603 deletions
diff --git a/api/current.txt b/api/current.txt index 0418cd9..7424f90 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5734,7 +5734,6 @@ package android.content { method public final android.os.Bundle call(android.net.Uri, java.lang.String, java.lang.String, android.os.Bundle); method public deprecated void cancelSync(android.net.Uri); method public static void cancelSync(android.accounts.Account, java.lang.String); - method public static void cancelSync(android.content.SyncRequest); method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]); method public static deprecated android.content.SyncInfo getCurrentSync(); method public static java.util.List<android.content.SyncInfo> getCurrentSyncs(); @@ -6713,9 +6712,7 @@ package android.content { field public final android.accounts.Account account; field public final java.lang.String authority; field public final android.os.Bundle extras; - field public final boolean isService; field public final long period; - field public final android.content.ComponentName service; } public class ReceiverCallNotAllowedException extends android.util.AndroidRuntimeException { @@ -6836,7 +6833,6 @@ package android.content { public class SyncRequest implements android.os.Parcelable { method public int describeContents(); - method public boolean isExpedited(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; } @@ -6844,18 +6840,15 @@ package android.content { public static class SyncRequest.Builder { ctor public SyncRequest.Builder(); method public android.content.SyncRequest build(); - method public android.content.SyncRequest.Builder setAllowMetered(boolean); + method public android.content.SyncRequest.Builder setDisallowMetered(boolean); method public android.content.SyncRequest.Builder setExpedited(boolean); method public android.content.SyncRequest.Builder setExtras(android.os.Bundle); method public android.content.SyncRequest.Builder setIgnoreBackoff(boolean); method public android.content.SyncRequest.Builder setIgnoreSettings(boolean); method public android.content.SyncRequest.Builder setManual(boolean); method public android.content.SyncRequest.Builder setNoRetry(boolean); - method public android.content.SyncRequest.Builder setPriority(int); method public android.content.SyncRequest.Builder setSyncAdapter(android.accounts.Account, java.lang.String); - method public android.content.SyncRequest.Builder setSyncAdapter(android.content.ComponentName); - method public android.content.SyncRequest.Builder setTransferSize(long, long); - method public android.content.SyncRequest.Builder syncOnce(long, long); + method public android.content.SyncRequest.Builder syncOnce(); method public android.content.SyncRequest.Builder syncPeriodic(long, long); } @@ -6882,12 +6875,6 @@ package android.content { field public boolean tooManyRetries; } - public abstract class SyncService extends android.app.Service { - ctor public SyncService(); - method public android.os.IBinder onBind(android.content.Intent); - method public abstract void onPerformSync(android.os.Bundle, android.content.SyncResult); - } - public class SyncStats implements android.os.Parcelable { ctor public SyncStats(); ctor public SyncStats(android.os.Parcel); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index a761a89..8a5a56c 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -141,7 +141,7 @@ public abstract class ContentResolver { public static final String SYNC_EXTRAS_PRIORITY = "sync_priority"; /** {@hide} Flag to allow sync to occur on metered network. */ - public static final String SYNC_EXTRAS_ALLOW_METERED = "allow_metered"; + public static final String SYNC_EXTRAS_DISALLOW_METERED = "disallow_metered"; /** * Set by the SyncManager to request that the SyncAdapter initialize itself for @@ -1669,7 +1669,7 @@ public abstract class ContentResolver { new SyncRequest.Builder() .setSyncAdapter(account, authority) .setExtras(extras) - .syncOnce(0, 0) // Immediate sync. + .syncOnce() .build(); requestSync(request); } @@ -1677,6 +1677,9 @@ public abstract class ContentResolver { /** * Register a sync with the SyncManager. These requests are built using the * {@link SyncRequest.Builder}. + * + * @param request The immutable SyncRequest object containing the sync parameters. Use + * {@link SyncRequest.Builder} to construct these. */ public static void requestSync(SyncRequest request) { try { @@ -1812,6 +1815,9 @@ public abstract class ContentResolver { * {@link #SYNC_EXTRAS_INITIALIZE}, {@link #SYNC_EXTRAS_FORCE}, * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL} set to true. * If any are supplied then an {@link IllegalArgumentException} will be thrown. + * <p>As of API level 19 this function introduces a default flexibility of ~4% (up to a maximum + * of one hour in the day) into the requested period. Use + * {@link SyncRequest.Builder#syncPeriodic(long, long)} to set this flexibility manually. * * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}. @@ -1875,22 +1881,6 @@ public abstract class ContentResolver { } /** - * Remove the specified sync. This will remove any syncs that have been scheduled to run, but - * will not cancel any running syncs. - * <p>This method requires the caller to hold the permission</p> - * If the request is for a periodic sync this will cancel future occurrences of the sync. - * - * It is possible to cancel a sync using a SyncRequest object that is different from the object - * with which you requested the sync. Do so by building a SyncRequest with exactly the same - * service/adapter, frequency, <b>and</b> extras bundle. - * - * @param request SyncRequest object containing information about sync to cancel. - */ - public static void cancelSync(SyncRequest request) { - // TODO: Finish this implementation. - } - - /** * Get the list of information about the periodic syncs for the given account and authority. * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#READ_SYNC_SETTINGS}. diff --git a/core/java/android/content/PeriodicSync.java b/core/java/android/content/PeriodicSync.java index 6aca151..b586eec 100644 --- a/core/java/android/content/PeriodicSync.java +++ b/core/java/android/content/PeriodicSync.java @@ -29,17 +29,13 @@ public class PeriodicSync implements Parcelable { public final Account account; /** The authority of the sync. Can be null. */ public final String authority; - /** The service for syncing, if this is an anonymous sync. Can be null.*/ - public final ComponentName service; /** Any extras that parameters that are to be passed to the sync adapter. */ public final Bundle extras; /** How frequently the sync should be scheduled, in seconds. Kept around for API purposes. */ public final long period; - /** Whether this periodic sync uses a service. */ - public final boolean isService; /** - * How much flexibility can be taken in scheduling the sync, in seconds. * {@hide} + * How much flexibility can be taken in scheduling the sync, in seconds. */ public final long flexTime; @@ -52,76 +48,44 @@ public class PeriodicSync implements Parcelable { public PeriodicSync(Account account, String authority, Bundle extras, long periodInSeconds) { this.account = account; this.authority = authority; - this.service = null; - this.isService = false; if (extras == null) { this.extras = new Bundle(); } else { this.extras = new Bundle(extras); } this.period = periodInSeconds; - // Old API uses default flex time. No-one should be using this ctor anyway. + // Initialise to a sane value. this.flexTime = 0L; } - // TODO: Add copy ctor from SyncRequest? - /** - * Create a copy of a periodic sync. * {@hide} + * Create a copy of a periodic sync. */ public PeriodicSync(PeriodicSync other) { this.account = other.account; this.authority = other.authority; - this.service = other.service; - this.isService = other.isService; this.extras = new Bundle(other.extras); this.period = other.period; this.flexTime = other.flexTime; } /** - * A PeriodicSync for a sync with a specified provider. * {@hide} + * A PeriodicSync for a sync with a specified provider. */ public PeriodicSync(Account account, String authority, Bundle extras, long period, long flexTime) { this.account = account; this.authority = authority; - this.service = null; - this.isService = false; - this.extras = new Bundle(extras); - this.period = period; - this.flexTime = flexTime; - } - - /** - * A PeriodicSync for a sync with a specified SyncService. - * {@hide} - */ - public PeriodicSync(ComponentName service, Bundle extras, - long period, - long flexTime) { - this.account = null; - this.authority = null; - this.service = service; - this.isService = true; this.extras = new Bundle(extras); this.period = period; this.flexTime = flexTime; } private PeriodicSync(Parcel in) { - this.isService = (in.readInt() != 0); - if (this.isService) { - this.service = in.readParcelable(null); - this.account = null; - this.authority = null; - } else { - this.account = in.readParcelable(null); - this.authority = in.readString(); - this.service = null; - } + this.account = in.readParcelable(null); + this.authority = in.readString(); this.extras = in.readBundle(); this.period = in.readLong(); this.flexTime = in.readLong(); @@ -134,13 +98,8 @@ public class PeriodicSync implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(isService ? 1 : 0); - if (account == null && authority == null) { - dest.writeParcelable(service, flags); - } else { - dest.writeParcelable(account, flags); - dest.writeString(authority); - } + dest.writeParcelable(account, flags); + dest.writeString(authority); dest.writeBundle(extras); dest.writeLong(period); dest.writeLong(flexTime); @@ -167,17 +126,8 @@ public class PeriodicSync implements Parcelable { return false; } final PeriodicSync other = (PeriodicSync) o; - if (this.isService != other.isService) { - return false; - } - boolean equal = false; - if (this.isService) { - equal = service.equals(other.service); - } else { - equal = account.equals(other.account) - && authority.equals(other.authority); - } - return equal + return account.equals(other.account) + && authority.equals(other.authority) && period == other.period && syncExtrasEquals(extras, other.extras); } @@ -208,7 +158,6 @@ public class PeriodicSync implements Parcelable { public String toString() { return "account: " + account + ", authority: " + authority + - ", service: " + service + ". period: " + period + "s " + ", flex: " + flexTime; } diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java index 4474c70..d4e0c2a 100644 --- a/core/java/android/content/SyncRequest.java +++ b/core/java/android/content/SyncRequest.java @@ -20,20 +20,19 @@ import android.accounts.Account; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.util.Pair; public class SyncRequest implements Parcelable { private static final String TAG = "SyncRequest"; - /** Account to pass to the sync adapter. Can be null. */ + /** Account to pass to the sync adapter. May be null. */ private final Account mAccountToSync; /** Authority string that corresponds to a ContentProvider. */ private final String mAuthority; - /** {@link SyncService} identifier. */ + /** Sync service identifier. May be null.*/ private final ComponentName mComponentInfo; /** Bundle containing user info as well as sync settings. */ private final Bundle mExtras; - /** Allow this sync request on metered networks. */ - private final boolean mAllowMetered; + /** Disallow this sync request on metered networks. */ + private final boolean mDisallowMetered; /** * Anticipated upload size in bytes. * TODO: Not yet used - we put this information into the bundle for simplicity. @@ -70,14 +69,18 @@ public class SyncRequest implements Parcelable { return mIsPeriodic; } + /** + * {@hide} + * @return whether this is an expedited sync. + */ public boolean isExpedited() { return mIsExpedited; } /** * {@hide} - * @return true if this sync uses an account/authority pair, or false if - * this is an anonymous sync bound to an @link AnonymousSyncService. + * @return true if this sync uses an account/authority pair, or false if this sync is bound to + * a Sync Service. */ public boolean hasAuthority() { return mIsAuthority; @@ -85,31 +88,30 @@ public class SyncRequest implements Parcelable { /** * {@hide} - * Throws a runtime IllegalArgumentException if this function is called for an - * anonymous sync. - * - * @return (Account, Provider) for this SyncRequest. + * @return account object for this sync. + * @throws IllegalArgumentException if this function is called for a request that does not + * specify an account/provider authority. */ - public Pair<Account, String> getProviderInfo() { + public Account getAccount() { if (!hasAuthority()) { - throw new IllegalArgumentException("Cannot getProviderInfo() for an anonymous sync."); + throw new IllegalArgumentException("Cannot getAccount() for a sync that does not" + + "specify an authority."); } - return Pair.create(mAccountToSync, mAuthority); + return mAccountToSync; } /** * {@hide} - * Throws a runtime IllegalArgumentException if this function is called for a - * SyncRequest that is bound to an account/provider. - * - * @return ComponentName for the service that this sync will bind to. + * @return provider for this sync. + * @throws IllegalArgumentException if this function is called for a request that does not + * specify an account/provider authority. */ - public ComponentName getService() { - if (hasAuthority()) { - throw new IllegalArgumentException( - "Cannot getAnonymousService() for a sync that has specified a provider."); + public String getProvider() { + if (!hasAuthority()) { + throw new IllegalArgumentException("Cannot getProvider() for a sync that does not" + + "specify a provider."); } - return mComponentInfo; + return mAuthority; } /** @@ -127,6 +129,7 @@ public class SyncRequest implements Parcelable { public long getSyncFlexTime() { return mSyncFlexTimeSecs; } + /** * {@hide} * @return the last point in time at which this sync must scheduled. @@ -159,7 +162,7 @@ public class SyncRequest implements Parcelable { parcel.writeLong(mSyncFlexTimeSecs); parcel.writeLong(mSyncRunTimeSecs); parcel.writeInt((mIsPeriodic ? 1 : 0)); - parcel.writeInt((mAllowMetered ? 1 : 0)); + parcel.writeInt((mDisallowMetered ? 1 : 0)); parcel.writeLong(mTxBytes); parcel.writeLong(mRxBytes); parcel.writeInt((mIsAuthority ? 1 : 0)); @@ -177,7 +180,7 @@ public class SyncRequest implements Parcelable { mSyncFlexTimeSecs = in.readLong(); mSyncRunTimeSecs = in.readLong(); mIsPeriodic = (in.readInt() != 0); - mAllowMetered = (in.readInt() != 0); + mDisallowMetered = (in.readInt() != 0); mTxBytes = in.readLong(); mRxBytes = in.readLong(); mIsAuthority = (in.readInt() != 0); @@ -207,13 +210,13 @@ public class SyncRequest implements Parcelable { // For now we merge the sync config extras & the custom extras into one bundle. // TODO: pass the configuration extras through separately. mExtras.putAll(b.mSyncConfigExtras); - mAllowMetered = b.mAllowMetered; + mDisallowMetered = b.mDisallowMetered; mTxBytes = b.mTxBytes; mRxBytes = b.mRxBytes; } /** - * Builder class for a @link SyncRequest. As you build your SyncRequest this class will also + * Builder class for a {@link SyncRequest}. As you build your SyncRequest this class will also * perform validation. */ public static class Builder { @@ -229,12 +232,9 @@ public class SyncRequest implements Parcelable { private static final int SYNC_TARGET_SERVICE = 1; /** Specify that this is a sync with a provider. */ private static final int SYNC_TARGET_ADAPTER = 2; - /** - * Earliest point of displacement into the future at which this sync can - * occur. - */ + /** Earliest point of displacement into the future at which this sync can occur. */ private long mSyncFlexTimeSecs; - /** Displacement into the future at which this sync must occur. */ + /** Latest point of displacement into the future at which this sync must occur. */ private long mSyncRunTimeSecs; /** * Sync configuration information - custom user data explicitly provided by the developer. @@ -253,7 +253,7 @@ public class SyncRequest implements Parcelable { /** Expected download transfer in bytes. */ private long mRxBytes = -1L; /** Whether or not this sync can occur on metered networks. Default false. */ - private boolean mAllowMetered; + private boolean mDisallowMetered; /** Priority of this sync relative to others from calling app [-2, 2]. Default 0. */ private int mPriority = 0; /** @@ -283,9 +283,8 @@ public class SyncRequest implements Parcelable { private boolean mExpedited; /** - * The {@link SyncService} component that - * contains the sync logic if this is a provider-less sync, otherwise - * null. + * The sync component that contains the sync logic if this is a provider-less sync, + * otherwise null. */ private ComponentName mComponentName; /** @@ -303,46 +302,28 @@ public class SyncRequest implements Parcelable { } /** - * Developer can define timing constraints for this one-shot request. - * These values are elapsed real-time. - * - * @param whenSeconds The time in seconds at which you want this - * sync to occur. - * @param beforeSeconds The amount of time in advance of whenSeconds that this - * sync may be permitted to occur. This is rounded up to a minimum of 5 - * seconds, for any sync for which whenSeconds > 5. + * Request that a sync occur immediately. * * Example * <pre> - * Perform an immediate sync. - * SyncRequest.Builder builder = (new SyncRequest.Builder()).syncOnce(0, 0); - * That is, a sync 0 seconds from now with 0 seconds of flex. - * - * Perform a sync in exactly 5 minutes. - * SyncRequest.Builder builder = - * new SyncRequest.Builder().syncOnce(5 * MIN_IN_SECS, 0); - * - * Perform a sync in 5 minutes, with one minute of leeway (between 4 and 5 minutes from - * now). - * SyncRequest.Builder builder = - * new SyncRequest.Builder().syncOnce(5 * MIN_IN_SECS, 1 * MIN_IN_SECS); + * SyncRequest.Builder builder = (new SyncRequest.Builder()).syncOnce(); * </pre> */ - public Builder syncOnce(long whenSeconds, long beforeSeconds) { + public Builder syncOnce() { if (mSyncType != SYNC_TYPE_UNKNOWN) { throw new IllegalArgumentException("Sync type has already been defined."); } mSyncType = SYNC_TYPE_ONCE; - setupInterval(whenSeconds, beforeSeconds); + setupInterval(0, 0); return this; } /** * Build a periodic sync. Either this or syncOnce() <b>must</b> be called for this builder. - * Syncs are identified by target {@link SyncService}/{@link android.provider} and by the - * contents of the extras bundle. - * You cannot reuse the same builder for one-time syncs after having specified a periodic - * sync (by calling this function). If you do, an <code>IllegalArgumentException</code> + * Syncs are identified by target {@link android.provider}/{@link android.accounts.Account} + * and by the contents of the extras bundle. + * You cannot reuse the same builder for one-time syncs (by calling this function) after + * having specified a periodic sync. If you do, an <code>IllegalArgumentException</code> * will be thrown. * * Example usage. @@ -394,6 +375,7 @@ public class SyncRequest implements Parcelable { } /** + * {@hide} * Developer can provide insight into their payload size; optional. -1 specifies unknown, * so that you are not restricted to defining both fields. * @@ -407,21 +389,20 @@ public class SyncRequest implements Parcelable { } /** - * @param allow false to allow this transfer on metered networks. Default true. + * @see android.net.ConnectivityManager#isActiveNetworkMetered() + * @param disallow true to enforce that this transfer not occur on metered networks. + * Default false. */ - public Builder setAllowMetered(boolean allow) { - mAllowMetered = true; + public Builder setDisallowMetered(boolean disallow) { + mDisallowMetered = disallow; return this; } /** - * Specify an authority and account for this transfer. Cannot be used with - * {@link #setSyncAdapter(ComponentName cname)}. + * Specify an authority and account for this transfer. * - * @param authority - * @param account Account to sync. Can be null unless this is a periodic - * sync, for which verification by the ContentResolver will - * fail. If a sync is performed without an account, the + * @param authority String identifying which content provider to sync. + * @param account Account to sync. Can be null unless this is a periodic sync. */ public Builder setSyncAdapter(Account account, String authority) { if (mSyncTarget != SYNC_TARGET_UNKNOWN) { @@ -435,26 +416,10 @@ public class SyncRequest implements Parcelable { } /** - * Specify the {@link SyncService} component for this sync. This is not validated until - * sync time so providing an incorrect component name here will not fail. Cannot be used - * with {@link #setSyncAdapter(Account account, String authority)}. - * - * @param cname ComponentName to identify your Anonymous service - */ - public Builder setSyncAdapter(ComponentName cname) { - if (mSyncTarget != SYNC_TARGET_UNKNOWN) { - throw new IllegalArgumentException("Sync target has already been defined."); - } - mSyncTarget = SYNC_TARGET_SERVICE; - mComponentName = cname; - mAccount = null; - mAuthority = null; - return this; - } - - /** - * Developer-provided extras handed back when sync actually occurs. This bundle is copied - * into the SyncRequest returned by {@link #build()}. + * Optional developer-provided extras handed back in + * {@link AbstractThreadedSyncAdapter#onPerformSync(Account, Bundle, String, + * ContentProviderClient, SyncResult)} occurs. This bundle is copied into the SyncRequest + * returned by {@link #build()}. * * Example: * <pre> @@ -468,7 +433,7 @@ public class SyncRequest implements Parcelable { * Bundle extras = new Bundle(); * extras.setString("data", syncData); * builder.setExtras(extras); - * ContentResolver.sync(builder.build()); // Each sync() request creates a unique sync. + * ContentResolver.sync(builder.build()); // Each sync() request is for a unique sync. * } * </pre> * Only values of the following types may be used in the extras bundle: @@ -509,7 +474,8 @@ public class SyncRequest implements Parcelable { /** * Convenience function for setting {@link ContentResolver#SYNC_EXTRAS_IGNORE_SETTINGS}. * - * Not valid for periodic sync and will throw an <code>IllegalArgumentException</code> in + * A sync can specify that system sync settings be ignored (user has turned sync off). Not + * valid for periodic sync and will throw an <code>IllegalArgumentException</code> in * {@link #build()}. * * @param ignoreSettings true to ignore the sync automatically settings. Default false. @@ -522,13 +488,13 @@ public class SyncRequest implements Parcelable { /** * Convenience function for setting {@link ContentResolver#SYNC_EXTRAS_IGNORE_BACKOFF}. * - * Ignoring back-off will force the sync scheduling process to ignore any back-off that was - * the result of a failed sync, as well as to invalidate any {@link SyncResult#delayUntil} - * value that may have been set by the adapter. Successive failures will not honor this - * flag. Not valid for periodic sync and will throw an <code>IllegalArgumentException</code> - * in {@link #build()}. + * Force the sync scheduling process to ignore any back-off that was the result of a failed + * sync, as well as to invalidate any {@link SyncResult#delayUntil} value that may have + * been set by the adapter. Successive failures will not honor this flag. Not valid for + * periodic sync and will throw an <code>IllegalArgumentException</code> in + * {@link #build()}. * - * @param ignoreBackoff ignore back off settings. Default false. + * @param ignoreBackoff ignore back-off settings. Default false. */ public Builder setIgnoreBackoff(boolean ignoreBackoff) { mIgnoreBackoff = ignoreBackoff; @@ -538,8 +504,9 @@ public class SyncRequest implements Parcelable { /** * Convenience function for setting {@link ContentResolver#SYNC_EXTRAS_MANUAL}. * - * Not valid for periodic sync and will throw an <code>IllegalArgumentException</code> in - * {@link #build()}. + * A manual sync is functionally equivalent to calling {@link #setIgnoreBackoff(boolean)} + * and {@link #setIgnoreSettings(boolean)}. Not valid for periodic sync and will throw an + * <code>IllegalArgumentException</code> in {@link #build()}. * * @param isManual User-initiated sync or not. Default false. */ @@ -549,7 +516,7 @@ public class SyncRequest implements Parcelable { } /** - * An expedited sync runs immediately and can preempt other non-expedited running syncs. + * An expedited sync runs immediately and will preempt another non-expedited running sync. * * Not valid for periodic sync and will throw an <code>IllegalArgumentException</code> in * {@link #build()}. @@ -562,6 +529,7 @@ public class SyncRequest implements Parcelable { } /** + * {@hide} * @param priority the priority of this request among all requests from the calling app. * Range of [-2,2] similar to how this is done with notifications. */ @@ -581,18 +549,18 @@ public class SyncRequest implements Parcelable { * builder. */ public SyncRequest build() { - // Validate the extras bundle - ContentResolver.validateSyncExtrasBundle(mCustomExtras); if (mCustomExtras == null) { mCustomExtras = new Bundle(); } + // Validate the extras bundle + ContentResolver.validateSyncExtrasBundle(mCustomExtras); // Combine builder extra flags into the config bundle. mSyncConfigExtras = new Bundle(); if (mIgnoreBackoff) { mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true); } - if (mAllowMetered) { - mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_ALLOW_METERED, true); + if (mDisallowMetered) { + mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, true); } if (mIgnoreSettings) { mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true); @@ -613,13 +581,22 @@ public class SyncRequest implements Parcelable { // If this is a periodic sync ensure than invalid extras were not set. validatePeriodicExtras(mCustomExtras); validatePeriodicExtras(mSyncConfigExtras); + // Verify that account and provider are not null. + if (mAccount == null) { + throw new IllegalArgumentException("Account must not be null for periodic" + + " sync."); + } + if (mAuthority == null) { + throw new IllegalArgumentException("Authority must not be null for periodic" + + " sync."); + } } else if (mSyncType == SYNC_TYPE_UNKNOWN) { throw new IllegalArgumentException("Must call either syncOnce() or syncPeriodic()"); } // Ensure that a target for the sync has been set. if (mSyncTarget == SYNC_TARGET_UNKNOWN) { - throw new IllegalArgumentException("Must specify an adapter with one of" - + "setSyncAdapter(ComponentName) or setSyncAdapter(Account, String"); + throw new IllegalArgumentException("Must specify an adapter with " + + "setSyncAdapter(Account, String"); } return new SyncRequest(this); } diff --git a/core/java/android/content/SyncService.java b/core/java/android/content/SyncService.java deleted file mode 100644 index 100fd40..0000000 --- a/core/java/android/content/SyncService.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content; - -import android.app.Service; -import android.os.Bundle; -import android.os.IBinder; -import android.os.Process; -import android.os.Trace; - -import com.android.internal.annotations.GuardedBy; - -import java.util.HashMap; - -/** - * Simplified @link android.content.AbstractThreadedSyncAdapter. Folds that - * behaviour into a service to which the system can bind when requesting an - * anonymous (providerless/accountless) sync. - * <p> - * In order to perform an anonymous sync operation you must extend this service, - * implementing the abstract methods. This service must then be declared in the - * application's manifest as usual. You can use this service for other work, however you - * <b> must not </b> override the onBind() method unless you know what you're doing, - * which limits the usefulness of this service for other work. - * - * <pre> - * <service ndroid:name=".MyAnonymousSyncService" android:permission="android.permission.SYNC" /> - * </pre> - * Like @link android.content.AbstractThreadedSyncAdapter this service supports - * multiple syncs at the same time. Each incoming startSync() with a unique tag - * will spawn a thread to do the work of that sync. If startSync() is called - * with a tag that already exists, a SyncResult.ALREADY_IN_PROGRESS is returned. - * Remember that your service will spawn multiple threads if you schedule multiple syncs - * at once, so if you mutate local objects you must ensure synchronization. - */ -public abstract class SyncService extends Service { - - /** SyncAdapter Instantiation that any anonymous syncs call. */ - private final AnonymousSyncAdapterImpl mSyncAdapter = new AnonymousSyncAdapterImpl(); - - /** Keep track of on-going syncs, keyed by tag. */ - @GuardedBy("mLock") - private final HashMap<Bundle, AnonymousSyncThread> - mSyncThreads = new HashMap<Bundle, AnonymousSyncThread>(); - /** Lock object for accessing the SyncThreads HashMap. */ - private final Object mSyncThreadLock = new Object(); - - @Override - public IBinder onBind(Intent intent) { - return mSyncAdapter.asBinder(); - } - - /** {@hide} */ - private class AnonymousSyncAdapterImpl extends IAnonymousSyncAdapter.Stub { - - @Override - public void startSync(ISyncContext syncContext, Bundle extras) { - // Wrap the provided Sync Context because it may go away by the time - // we call it. - final SyncContext syncContextClient = new SyncContext(syncContext); - boolean alreadyInProgress = false; - synchronized (mSyncThreadLock) { - if (mSyncThreads.containsKey(extras)) { - // Don't want to call back to SyncManager while still - // holding lock. - alreadyInProgress = true; - } else { - AnonymousSyncThread syncThread = new AnonymousSyncThread( - syncContextClient, extras); - mSyncThreads.put(extras, syncThread); - syncThread.start(); - } - } - if (alreadyInProgress) { - syncContextClient.onFinished(SyncResult.ALREADY_IN_PROGRESS); - } - } - - /** - * Used by the SM to cancel a specific sync using the {@link - * com.android.server.content.SyncManager.ActiveSyncContext} as a handle. - */ - @Override - public void cancelSync(ISyncContext syncContext) { - AnonymousSyncThread runningSync = null; - synchronized (mSyncThreadLock) { - for (AnonymousSyncThread thread : mSyncThreads.values()) { - if (thread.mSyncContext.getSyncContextBinder() == syncContext.asBinder()) { - runningSync = thread; - break; - } - } - } - if (runningSync != null) { - runningSync.interrupt(); - } - } - } - - /** - * {@hide} - * Similar to {@link android.content.AbstractThreadedSyncAdapter.SyncThread}. However while - * the ATSA considers an already in-progress sync to be if the account provided is currently - * syncing, this anonymous sync has no notion of account and therefore considers a sync unique - * if the provided bundle is different. - */ - private class AnonymousSyncThread extends Thread { - private final SyncContext mSyncContext; - private final Bundle mExtras; - - public AnonymousSyncThread(SyncContext syncContext, Bundle extras) { - mSyncContext = syncContext; - mExtras = extras; - } - - @Override - public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - - Trace.traceBegin(Trace.TRACE_TAG_SYNC_MANAGER, getApplication().getPackageName()); - - SyncResult syncResult = new SyncResult(); - try { - if (isCancelled()) { - return; - } - // Run the sync based off of the provided code. - SyncService.this.onPerformSync(mExtras, syncResult); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_SYNC_MANAGER); - if (!isCancelled()) { - mSyncContext.onFinished(syncResult); - } - // Synchronize so that the assignment will be seen by other - // threads - // that also synchronize accesses to mSyncThreads. - synchronized (mSyncThreadLock) { - mSyncThreads.remove(mExtras); - } - } - } - - private boolean isCancelled() { - return Thread.currentThread().isInterrupted(); - } - } - - /** - * Initiate an anonymous sync using this service. SyncAdapter-specific - * parameters may be specified in extras, which is guaranteed to not be - * null. - */ - public abstract void onPerformSync(Bundle extras, SyncResult syncResult); - -} diff --git a/services/java/com/android/server/content/ContentService.java b/services/java/com/android/server/content/ContentService.java index a56af08..7c82821 100644 --- a/services/java/com/android/server/content/ContentService.java +++ b/services/java/com/android/server/content/ContentService.java @@ -19,7 +19,6 @@ package com.android.server.content; import android.Manifest; import android.accounts.Account; import android.app.ActivityManager; -import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.IContentService; @@ -363,8 +362,8 @@ public final class ContentService extends IContentService.Stub { if (syncManager != null) { if (request.hasAuthority()) { // Sync Adapter registered with the system - old API. - final Account account = request.getProviderInfo().first; - final String provider = request.getProviderInfo().second; + final Account account = request.getAccount(); + final String provider = request.getProvider(); if (request.isPeriodic()) { mContext.enforceCallingOrSelfPermission( Manifest.permission.WRITE_SYNC_SETTINGS, @@ -386,20 +385,7 @@ public final class ContentService extends IContentService.Stub { false /* onlyThoseWithUnknownSyncableState */); } } else { - // Anonymous sync - new API. - final ComponentName syncService = request.getService(); - if (request.isPeriodic()) { - throw new RuntimeException("Periodic anonymous syncs not implemented yet."); - } else { - long beforeRuntimeMillis = (flextime) * 1000; - long runtimeMillis = runAtTime * 1000; - syncManager.scheduleSync( - syncService, userId, uId, extras, - beforeRuntimeMillis, - runtimeMillis, - false /* onlyThoseWithUnknownSyncableState */); // Empty function. - throw new RuntimeException("One-off anonymous syncs not implemented yet."); - } + Log.w(TAG, "Unrecognised sync parameters, doing nothing."); } } } finally { diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java index a6b69a2..9a41166 100644 --- a/services/java/com/android/server/content/SyncManager.java +++ b/services/java/com/android/server/content/SyncManager.java @@ -87,6 +87,7 @@ import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -539,177 +540,6 @@ public class SyncManager { } /** - * Initiate a sync using the new anonymous service API. - * TODO: Implement. - * @param cname SyncService component bound to in order to perform the sync. - * @param userId the id of the user whose accounts are to be synced. If userId is USER_ALL, - * then all users' accounts are considered. - * @param uid Linux uid of the application that is performing the sync. - * @param extras a Map of SyncAdapter-specific information to control - * syncs of a specific provider. Can be null. - * @param beforeRunTimeMillis - * @param runtimeMillis - */ - public void scheduleSync(ComponentName cname, int userId, int uid, Bundle extras, - long beforeRunTimeMillis, long runtimeMillis, - boolean onlyThoseWithUnknownSyncableState) { -/** - boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE); - - final boolean backgroundDataUsageAllowed = !mBootCompleted || - getConnectivityManager().getBackgroundDataSetting(); - - if (extras == null) { - extras = new Bundle(); - } - if (isLoggable) { - Log.e(TAG, requestedAccount + " " + extras.toString() + " " + requestedAuthority); - } - Boolean expedited = extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false); - if (expedited) { - runtimeMillis = -1; // this means schedule at the front of the queue - } - - AccountAndUser[] accounts; - if (requestedAccount != null && userId != UserHandle.USER_ALL) { - accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) }; - } else { - // if the accounts aren't configured yet then we can't support an account-less - // sync request - accounts = mRunningAccounts; - if (accounts.length == 0) { - if (isLoggable) { - Log.v(TAG, "scheduleSync: no accounts configured, dropping"); - } - return; - } - } - - final boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false); - final boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false); - if (manualSync) { - extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true); - extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true); - } - final boolean ignoreSettings = - extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false); - - int source; - if (uploadOnly) { - source = SyncStorageEngine.SOURCE_LOCAL; - } else if (manualSync) { - source = SyncStorageEngine.SOURCE_USER; - } else if (requestedAuthority == null) { - source = SyncStorageEngine.SOURCE_POLL; - } else { - // this isn't strictly server, since arbitrary callers can (and do) request - // a non-forced two-way sync on a specific url - source = SyncStorageEngine.SOURCE_SERVER; - } - - for (AccountAndUser account : accounts) { - // Compile a list of authorities that have sync adapters. - // For each authority sync each account that matches a sync adapter. - final HashSet<String> syncableAuthorities = new HashSet<String>(); - for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter : - mSyncAdapters.getAllServices(account.userId)) { - syncableAuthorities.add(syncAdapter.type.authority); - } - - // if the url was specified then replace the list of authorities - // with just this authority or clear it if this authority isn't - // syncable - if (requestedAuthority != null) { - final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority); - syncableAuthorities.clear(); - if (hasSyncAdapter) syncableAuthorities.add(requestedAuthority); - } - - for (String authority : syncableAuthorities) { - int isSyncable = getIsSyncable(account.account, account.userId, - authority); - if (isSyncable == 0) { - continue; - } - final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo; - syncAdapterInfo = mSyncAdapters.getServiceInfo( - SyncAdapterType.newKey(authority, account.account.type), account.userId); - if (syncAdapterInfo == null) { - continue; - } - final boolean allowParallelSyncs = syncAdapterInfo.type.allowParallelSyncs(); - final boolean isAlwaysSyncable = syncAdapterInfo.type.isAlwaysSyncable(); - if (isSyncable < 0 && isAlwaysSyncable) { - mSyncStorageEngine.setIsSyncable(account.account, account.userId, authority, 1); - isSyncable = 1; - } - if (onlyThoseWithUnkownSyncableState && isSyncable >= 0) { - continue; - } - if (!syncAdapterInfo.type.supportsUploading() && uploadOnly) { - continue; - } - - // always allow if the isSyncable state is unknown - boolean syncAllowed = - (isSyncable < 0) - || ignoreSettings - || (backgroundDataUsageAllowed - && mSyncStorageEngine.getMasterSyncAutomatically(account.userId) - && mSyncStorageEngine.getSyncAutomatically(account.account, - account.userId, authority)); - if (!syncAllowed) { - if (isLoggable) { - Log.d(TAG, "scheduleSync: sync of " + account + ", " + authority - + " is not allowed, dropping request"); - } - continue; - } - - Pair<Long, Long> backoff = mSyncStorageEngine - .getBackoff(account.account, account.userId, authority); - long delayUntil = mSyncStorageEngine.getDelayUntilTime(account.account, - account.userId, authority); - final long backoffTime = backoff != null ? backoff.first : 0; - if (isSyncable < 0) { - // Initialisation sync. - Bundle newExtras = new Bundle(); - newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true); - if (isLoggable) { - Log.v(TAG, "schedule initialisation Sync:" - + ", delay until " + delayUntil - + ", run by " + 0 - + ", source " + source - + ", account " + account - + ", authority " + authority - + ", extras " + newExtras); - } - scheduleSyncOperation( - new SyncOperation(account.account, account.userId, reason, source, - authority, newExtras, 0 /* immediate , 0 /* No flex time, - backoffTime, delayUntil, allowParallelSyncs)); - } - if (!onlyThoseWithUnkownSyncableState) { - if (isLoggable) { - Log.v(TAG, "scheduleSync:" - + " delay until " + delayUntil - + " run by " + runtimeMillis - + " flex " + beforeRuntimeMillis - + ", source " + source - + ", account " + account - + ", authority " + authority - + ", extras " + extras); - } - scheduleSyncOperation( - new SyncOperation(account.account, account.userId, reason, source, - authority, extras, runtimeMillis, beforeRuntimeMillis, - backoffTime, delayUntil, allowParallelSyncs)); - } - } - }*/ - } - - /** * Initiate a sync. This can start a sync for all providers * (pass null to url, set onlyTicklable to false), only those * providers that are marked as ticklable (pass null to url, @@ -2190,17 +2020,14 @@ public class SyncManager { for (int i = 0, N = authorityInfo.periodicSyncs.size(); i < N; i++) { final PeriodicSync sync = authorityInfo.periodicSyncs.get(i); final Bundle extras = sync.extras; - final Long periodInMillis = sync.period * 1000; - final Long flexInMillis = sync.flexTime * 1000; + final long periodInMillis = sync.period * 1000; + final long flexInMillis = sync.flexTime * 1000; // Skip if the period is invalid. if (periodInMillis <= 0) { continue; } // Find when this periodic sync was last scheduled to run. final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i); - final long shiftedLastPollTimeAbsolute = - (0 < lastPollTimeAbsolute - mSyncRandomOffsetMillis) ? - (lastPollTimeAbsolute - mSyncRandomOffsetMillis) : 0; long remainingMillis = periodInMillis - (shiftedNowAbsolute % periodInMillis); long timeSinceLastRunMillis @@ -2217,7 +2044,6 @@ public class SyncManager { + " remaining: " + (remainingMillis) + " time_since_last: " + timeSinceLastRunMillis + " last poll absol: " + lastPollTimeAbsolute - + " last poll shifed: " + shiftedLastPollTimeAbsolute + " shifted now: " + shiftedNowAbsolute + " run_early: " + runEarly); } @@ -2392,6 +2218,15 @@ public class SyncManager { } continue; } + + // If the op isn't allowed on metered networks and we're on one, drop it. + if (getConnectivityManager().isActiveNetworkMetered() + && op.isMeteredDisallowed()) { + operationIterator.remove(); + mSyncStorageEngine.deleteFromPending(op.pendingOperation); + continue; + } + // TODO: change this behaviour for non-registered syncs. final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo; syncAdapterInfo = mSyncAdapters.getServiceInfo( diff --git a/services/java/com/android/server/content/SyncOperation.java b/services/java/com/android/server/content/SyncOperation.java index ce1dde4..4856747 100644 --- a/services/java/com/android/server/content/SyncOperation.java +++ b/services/java/com/android/server/content/SyncOperation.java @@ -111,40 +111,6 @@ public class SyncOperation implements Comparable { this.key = toKey(); } - public SyncOperation(SyncRequest request, int userId, int reason, int source, long backoff, - long delayUntil, boolean allowParallelSyncs) { - if (request.hasAuthority()) { - Pair<Account, String> providerInfo = request.getProviderInfo(); - this.account = providerInfo.first; - this.authority = providerInfo.second; - this.service = null; - } else { - this.service = request.getService(); - this.account = null; - this.authority = null; - } - this.userId = userId; - this.reason = reason; - this.syncSource = source; - this.allowParallelSyncs = allowParallelSyncs; - this.extras = new Bundle(extras); - cleanBundle(this.extras); - this.delayUntil = delayUntil; - this.backoff = backoff; - final long now = SystemClock.elapsedRealtime(); - if (request.isExpedited()) { - this.expedited = true; - this.latestRunTime = now; - this.flexTime = 0; - } else { - this.expedited = false; - this.latestRunTime = now + (request.getSyncRunTime() * 1000); - this.flexTime = request.getSyncFlexTime() * 1000; - } - updateEffectiveRunTime(); - this.key = toKey(); - } - /** * Make sure the bundle attached to this SyncOperation doesn't have unnecessary * flags set. @@ -159,7 +125,7 @@ public class SyncOperation implements Comparable { removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS); removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_EXPEDITED); removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS); - removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_ALLOW_METERED); + removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DISALLOW_METERED); // Remove Config data. bundle.remove(ContentResolver.SYNC_EXTRAS_EXPECTED_UPLOAD); @@ -245,8 +211,8 @@ public class SyncOperation implements Comparable { } } - public boolean isMetered() { - return extras.getBoolean(ContentResolver.SYNC_EXTRAS_ALLOW_METERED, false); + public boolean isMeteredDisallowed() { + return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false); } public boolean isInitialization() { diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/java/com/android/server/content/SyncStorageEngine.java index e3693f8..1b9ed98 100644 --- a/services/java/com/android/server/content/SyncStorageEngine.java +++ b/services/java/com/android/server/content/SyncStorageEngine.java @@ -71,7 +71,7 @@ import java.util.TimeZone; public class SyncStorageEngine extends Handler { private static final String TAG = "SyncManager"; - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; private static final String TAG_FILE = "SyncManagerFile"; private static final String XML_ATTR_NEXT_AUTHORITY_ID = "nextAuthorityId"; |