blob: 485674782aeb9ffe3765c4d77892bf7230061ceb [file] [log] [blame]
Kenny Root15a4d2f2010-03-11 18:20:12 -08001/*
2 * Copyright (C) 2010 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
Jeff Sharkey7a96c392012-11-15 14:01:46 -080017package com.android.server.content;
Fred Quintana307da1a2010-01-21 14:24:20 -080018
19import android.accounts.Account;
Alon Albert57286f92012-10-09 14:21:38 -070020import android.content.pm.PackageManager;
Matthew Williamsfa774182013-06-18 15:44:11 -070021import android.content.ComponentName;
Jeff Sharkey7a96c392012-11-15 14:01:46 -080022import android.content.ContentResolver;
Matthew Williamsfa774182013-06-18 15:44:11 -070023import android.content.SyncRequest;
Fred Quintana307da1a2010-01-21 14:24:20 -080024import android.os.Bundle;
25import android.os.SystemClock;
Matthew Williamsfa774182013-06-18 15:44:11 -070026import android.util.Pair;
Fred Quintana307da1a2010-01-21 14:24:20 -080027
28/**
29 * Value type that represents a sync operation.
Matthew Williamsfa774182013-06-18 15:44:11 -070030 * TODO: This is the class to flesh out with all the scheduling data - metered/unmetered,
31 * transfer-size, etc.
32 * {@hide}
Fred Quintana307da1a2010-01-21 14:24:20 -080033 */
34public class SyncOperation implements Comparable {
Alon Albert57286f92012-10-09 14:21:38 -070035 public static final int REASON_BACKGROUND_DATA_SETTINGS_CHANGED = -1;
36 public static final int REASON_ACCOUNTS_UPDATED = -2;
37 public static final int REASON_SERVICE_CHANGED = -3;
38 public static final int REASON_PERIODIC = -4;
39 public static final int REASON_IS_SYNCABLE = -5;
Matthew Williamsfa774182013-06-18 15:44:11 -070040 /** Sync started because it has just been set to sync automatically. */
Alon Albert57286f92012-10-09 14:21:38 -070041 public static final int REASON_SYNC_AUTO = -6;
Matthew Williamsfa774182013-06-18 15:44:11 -070042 /** Sync started because master sync automatically has been set to true. */
Alon Albert57286f92012-10-09 14:21:38 -070043 public static final int REASON_MASTER_SYNC_AUTO = -7;
44 public static final int REASON_USER_START = -8;
45
46 private static String[] REASON_NAMES = new String[] {
47 "DataSettingsChanged",
48 "AccountsUpdated",
49 "ServiceChanged",
50 "Periodic",
51 "IsSyncable",
52 "AutoSync",
53 "MasterSyncAuto",
54 "UserStart",
55 };
56
Matthew Williamsfa774182013-06-18 15:44:11 -070057 /** Account info to identify a SyncAdapter registered with the system. */
Fred Quintana307da1a2010-01-21 14:24:20 -080058 public final Account account;
Matthew Williamsfa774182013-06-18 15:44:11 -070059 /** Authority info to identify a SyncAdapter registered with the system. */
60 public final String authority;
61 /** Service to which this operation will bind to perform the sync. */
62 public final ComponentName service;
Amith Yamasani04e0d262012-02-14 11:50:53 -080063 public final int userId;
Alon Albert57286f92012-10-09 14:21:38 -070064 public final int reason;
Fred Quintana307da1a2010-01-21 14:24:20 -080065 public int syncSource;
Fred Quintana0c4d04a2010-11-03 17:02:55 -070066 public final boolean allowParallelSyncs;
Fred Quintana307da1a2010-01-21 14:24:20 -080067 public Bundle extras;
68 public final String key;
Fred Quintana307da1a2010-01-21 14:24:20 -080069 public boolean expedited;
70 public SyncStorageEngine.PendingOperation pendingOperation;
Matthew Williamsfa774182013-06-18 15:44:11 -070071 /** Elapsed real time in millis at which to run this sync. */
72 public long latestRunTime;
73 /** Set by the SyncManager in order to delay retries. */
Fred Quintana918339a2010-10-05 14:00:39 -070074 public Long backoff;
Matthew Williamsfa774182013-06-18 15:44:11 -070075 /** Specified by the adapter to delay subsequent sync operations. */
Fred Quintana918339a2010-10-05 14:00:39 -070076 public long delayUntil;
Matthew Williamsfa774182013-06-18 15:44:11 -070077 /**
78 * Elapsed real time in millis when this sync will be run.
79 * Depends on max(backoff, latestRunTime, and delayUntil).
80 */
Fred Quintana918339a2010-10-05 14:00:39 -070081 public long effectiveRunTime;
Matthew Williamsfa774182013-06-18 15:44:11 -070082 /** Amount of time before {@link effectiveRunTime} from which this sync can run. */
83 public long flexTime;
Fred Quintana307da1a2010-01-21 14:24:20 -080084
Alon Albert57286f92012-10-09 14:21:38 -070085 public SyncOperation(Account account, int userId, int reason, int source, String authority,
Matthew Williamsfa774182013-06-18 15:44:11 -070086 Bundle extras, long runTimeFromNow, long flexTime, long backoff,
87 long delayUntil, boolean allowParallelSyncs) {
88 this.service = null;
Fred Quintana307da1a2010-01-21 14:24:20 -080089 this.account = account;
Matthew Williamsfa774182013-06-18 15:44:11 -070090 this.authority = authority;
Amith Yamasani04e0d262012-02-14 11:50:53 -080091 this.userId = userId;
Alon Albert57286f92012-10-09 14:21:38 -070092 this.reason = reason;
Fred Quintana307da1a2010-01-21 14:24:20 -080093 this.syncSource = source;
Fred Quintana0c4d04a2010-11-03 17:02:55 -070094 this.allowParallelSyncs = allowParallelSyncs;
Fred Quintana307da1a2010-01-21 14:24:20 -080095 this.extras = new Bundle(extras);
Matthew Williamsfa774182013-06-18 15:44:11 -070096 cleanBundle(this.extras);
Fred Quintana918339a2010-10-05 14:00:39 -070097 this.delayUntil = delayUntil;
98 this.backoff = backoff;
Fred Quintana307da1a2010-01-21 14:24:20 -080099 final long now = SystemClock.elapsedRealtime();
Matthew Williams68e39c32013-07-25 16:40:23 -0700100 // Checks the extras bundle. Must occur after we set the internal bundle.
Matthew Williamsfa774182013-06-18 15:44:11 -0700101 if (runTimeFromNow < 0 || isExpedited()) {
Fred Quintana307da1a2010-01-21 14:24:20 -0800102 this.expedited = true;
Matthew Williamsfa774182013-06-18 15:44:11 -0700103 this.latestRunTime = now;
104 this.flexTime = 0;
Fred Quintana307da1a2010-01-21 14:24:20 -0800105 } else {
106 this.expedited = false;
Matthew Williamsfa774182013-06-18 15:44:11 -0700107 this.latestRunTime = now + runTimeFromNow;
108 this.flexTime = flexTime;
Fred Quintana307da1a2010-01-21 14:24:20 -0800109 }
Fred Quintana918339a2010-10-05 14:00:39 -0700110 updateEffectiveRunTime();
Fred Quintana307da1a2010-01-21 14:24:20 -0800111 this.key = toKey();
112 }
113
Matthew Williamsfa774182013-06-18 15:44:11 -0700114 /**
115 * Make sure the bundle attached to this SyncOperation doesn't have unnecessary
116 * flags set.
117 * @param bundle to clean.
118 */
119 private void cleanBundle(Bundle bundle) {
120 removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_UPLOAD);
121 removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_MANUAL);
122 removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS);
123 removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF);
124 removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY);
125 removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS);
126 removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_EXPEDITED);
127 removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS);
Matthew Williams62222882013-08-20 15:32:20 -0700128 removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DISALLOW_METERED);
Matthew Williamsfa774182013-06-18 15:44:11 -0700129
130 // Remove Config data.
131 bundle.remove(ContentResolver.SYNC_EXTRAS_EXPECTED_UPLOAD);
132 bundle.remove(ContentResolver.SYNC_EXTRAS_EXPECTED_DOWNLOAD);
133 }
134
135 private void removeFalseExtra(Bundle bundle, String extraName) {
136 if (!bundle.getBoolean(extraName, false)) {
137 bundle.remove(extraName);
Fred Quintana307da1a2010-01-21 14:24:20 -0800138 }
139 }
140
Matthew Williamsfa774182013-06-18 15:44:11 -0700141 /** Only used to immediately reschedule a sync. */
Fred Quintana307da1a2010-01-21 14:24:20 -0800142 SyncOperation(SyncOperation other) {
Matthew Williamsfa774182013-06-18 15:44:11 -0700143 this.service = other.service;
Fred Quintana307da1a2010-01-21 14:24:20 -0800144 this.account = other.account;
Matthew Williamsfa774182013-06-18 15:44:11 -0700145 this.authority = other.authority;
Amith Yamasani04e0d262012-02-14 11:50:53 -0800146 this.userId = other.userId;
Alon Albert57286f92012-10-09 14:21:38 -0700147 this.reason = other.reason;
Fred Quintana307da1a2010-01-21 14:24:20 -0800148 this.syncSource = other.syncSource;
Fred Quintana307da1a2010-01-21 14:24:20 -0800149 this.extras = new Bundle(other.extras);
150 this.expedited = other.expedited;
Matthew Williamsfa774182013-06-18 15:44:11 -0700151 this.latestRunTime = SystemClock.elapsedRealtime();
152 this.flexTime = 0L;
Fred Quintana918339a2010-10-05 14:00:39 -0700153 this.backoff = other.backoff;
Fred Quintana0c4d04a2010-11-03 17:02:55 -0700154 this.allowParallelSyncs = other.allowParallelSyncs;
Fred Quintana918339a2010-10-05 14:00:39 -0700155 this.updateEffectiveRunTime();
Fred Quintana307da1a2010-01-21 14:24:20 -0800156 this.key = toKey();
157 }
158
Matthew Williamsfa774182013-06-18 15:44:11 -0700159 @Override
Fred Quintana307da1a2010-01-21 14:24:20 -0800160 public String toString() {
Alon Albert57286f92012-10-09 14:21:38 -0700161 return dump(null, true);
Fred Quintana918339a2010-10-05 14:00:39 -0700162 }
163
Alon Albert57286f92012-10-09 14:21:38 -0700164 public String dump(PackageManager pm, boolean useOneLine) {
Alon Albert8e285552012-09-17 15:05:27 -0700165 StringBuilder sb = new StringBuilder()
166 .append(account.name)
167 .append(" u")
168 .append(userId).append(" (")
169 .append(account.type)
170 .append(")")
171 .append(", ")
172 .append(authority)
173 .append(", ")
174 .append(SyncStorageEngine.SOURCES[syncSource])
Matthew Williamsfa774182013-06-18 15:44:11 -0700175 .append(", latestRunTime ")
176 .append(latestRunTime);
Fred Quintana918339a2010-10-05 14:00:39 -0700177 if (expedited) {
178 sb.append(", EXPEDITED");
179 }
Alon Albert57286f92012-10-09 14:21:38 -0700180 sb.append(", reason: ");
181 sb.append(reasonToString(pm, reason));
Fred Quintana918339a2010-10-05 14:00:39 -0700182 if (!useOneLine && !extras.keySet().isEmpty()) {
183 sb.append("\n ");
184 extrasToStringBuilder(extras, sb);
185 }
Fred Quintana307da1a2010-01-21 14:24:20 -0800186 return sb.toString();
187 }
188
Alon Albert57286f92012-10-09 14:21:38 -0700189 public static String reasonToString(PackageManager pm, int reason) {
190 if (reason >= 0) {
191 if (pm != null) {
192 final String[] packages = pm.getPackagesForUid(reason);
193 if (packages != null && packages.length == 1) {
194 return packages[0];
195 }
196 final String name = pm.getNameForUid(reason);
197 if (name != null) {
198 return name;
199 }
200 return String.valueOf(reason);
201 } else {
202 return String.valueOf(reason);
203 }
204 } else {
205 final int index = -reason - 1;
206 if (index >= REASON_NAMES.length) {
207 return String.valueOf(reason);
208 } else {
209 return REASON_NAMES[index];
210 }
211 }
212 }
213
Matthew Williams62222882013-08-20 15:32:20 -0700214 public boolean isMeteredDisallowed() {
215 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
Matthew Williamsfa774182013-06-18 15:44:11 -0700216 }
217
Fred Quintana918339a2010-10-05 14:00:39 -0700218 public boolean isInitialization() {
219 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
220 }
221
Fred Quintanadc475562012-05-04 15:51:54 -0700222 public boolean isExpedited() {
Matthew Williamsfa774182013-06-18 15:44:11 -0700223 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false) || expedited;
Fred Quintanadc475562012-05-04 15:51:54 -0700224 }
225
Fred Quintana918339a2010-10-05 14:00:39 -0700226 public boolean ignoreBackoff() {
227 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false);
228 }
229
Matthew Williamsfa774182013-06-18 15:44:11 -0700230 /** Changed in V3. */
Fred Quintana307da1a2010-01-21 14:24:20 -0800231 private String toKey() {
232 StringBuilder sb = new StringBuilder();
Matthew Williamsfa774182013-06-18 15:44:11 -0700233 if (service == null) {
234 sb.append("authority: ").append(authority);
235 sb.append(" account {name=" + account.name + ", user=" + userId + ", type=" + account.type
236 + "}");
237 } else {
238 sb.append("service {package=" )
239 .append(service.getPackageName())
240 .append(" user=")
241 .append(userId)
242 .append(", class=")
243 .append(service.getClassName())
244 .append("}");
245 }
Fred Quintana307da1a2010-01-21 14:24:20 -0800246 sb.append(" extras: ");
Fred Quintana918339a2010-10-05 14:00:39 -0700247 extrasToStringBuilder(extras, sb);
Fred Quintana307da1a2010-01-21 14:24:20 -0800248 return sb.toString();
249 }
250
Fred Quintana918339a2010-10-05 14:00:39 -0700251 public static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
Fred Quintana307da1a2010-01-21 14:24:20 -0800252 sb.append("[");
253 for (String key : bundle.keySet()) {
Fred Quintana307da1a2010-01-21 14:24:20 -0800254 sb.append(key).append("=").append(bundle.get(key)).append(" ");
255 }
256 sb.append("]");
257 }
258
Matthew Williamsfa774182013-06-18 15:44:11 -0700259 /**
260 * Update the effective run time of this Operation based on latestRunTime (specified at
261 * creation time of sync), delayUntil (specified by SyncAdapter), or backoff (specified by
262 * SyncManager on soft failures).
263 */
Fred Quintana918339a2010-10-05 14:00:39 -0700264 public void updateEffectiveRunTime() {
Matthew Williamsfa774182013-06-18 15:44:11 -0700265 // Regardless of whether we're in backoff or honouring a delayUntil, we still incorporate
266 // the flex time provided by the developer.
267 effectiveRunTime = ignoreBackoff() ?
268 latestRunTime :
269 Math.max(Math.max(latestRunTime, delayUntil), backoff);
Fred Quintana918339a2010-10-05 14:00:39 -0700270 }
271
Matthew Williamsfa774182013-06-18 15:44:11 -0700272 /**
Matthew Williams7986fe42013-07-29 16:56:23 -0700273 * SyncOperations are sorted based on their earliest effective run time.
274 * This comparator is used to sort the SyncOps at a given time when
275 * deciding which to run, so earliest run time is the best criteria.
Matthew Williamsfa774182013-06-18 15:44:11 -0700276 */
277 @Override
Fred Quintana307da1a2010-01-21 14:24:20 -0800278 public int compareTo(Object o) {
Matthew Williamsfa774182013-06-18 15:44:11 -0700279 SyncOperation other = (SyncOperation) o;
Fred Quintana918339a2010-10-05 14:00:39 -0700280 if (expedited != other.expedited) {
281 return expedited ? -1 : 1;
282 }
Matthew Williams7986fe42013-07-29 16:56:23 -0700283 long thisIntervalStart = Math.max(effectiveRunTime - flexTime, 0);
284 long otherIntervalStart = Math.max(
285 other.effectiveRunTime - other.flexTime, 0);
286 if (thisIntervalStart < otherIntervalStart) {
287 return -1;
288 } else if (otherIntervalStart < thisIntervalStart) {
289 return 1;
290 } else {
Fred Quintana307da1a2010-01-21 14:24:20 -0800291 return 0;
292 }
Fred Quintana307da1a2010-01-21 14:24:20 -0800293 }
294}