blob: 7d2cc0035847d670d675a9b93c7e699e94dd01a6 [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;
Dianne Hackborn1085ff62016-02-23 17:04:58 -080020import android.app.job.JobInfo;
Jeff Sharkey7a96c392012-11-15 14:01:46 -080021import android.content.ContentResolver;
Makoto Onuki15e7a252017-06-08 17:12:05 -070022import android.content.pm.PackageManager;
Fred Quintana307da1a2010-01-21 14:24:20 -080023import android.os.Bundle;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000024import android.os.PersistableBundle;
Makoto Onuki15e7a252017-06-08 17:12:05 -070025import android.os.SystemClock;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070026import android.os.UserHandle;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000027import android.util.Slog;
Fred Quintana307da1a2010-01-21 14:24:20 -080028
29/**
30 * Value type that represents a sync operation.
Shreyas Basarge8c834c02016-01-07 13:53:16 +000031 * This holds all information related to a sync operation - both one off and periodic.
32 * Data stored in this is used to schedule a job with the JobScheduler.
Matthew Williamsfa774182013-06-18 15:44:11 -070033 * {@hide}
Fred Quintana307da1a2010-01-21 14:24:20 -080034 */
Shreyas Basarge8c834c02016-01-07 13:53:16 +000035public class SyncOperation {
Matthew Williams56dbf8f2013-07-26 12:56:39 -070036 public static final String TAG = "SyncManager";
37
Shreyas Basarge8c834c02016-01-07 13:53:16 +000038 /**
39 * This is used in the {@link #sourcePeriodicId} field if the operation is not initiated by a failed
40 * periodic sync.
41 */
42 public static final int NO_JOB_ID = -1;
43
Alon Albert57286f92012-10-09 14:21:38 -070044 public static final int REASON_BACKGROUND_DATA_SETTINGS_CHANGED = -1;
45 public static final int REASON_ACCOUNTS_UPDATED = -2;
46 public static final int REASON_SERVICE_CHANGED = -3;
47 public static final int REASON_PERIODIC = -4;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070048 /** Sync started because it has just been set to isSyncable. */
Alon Albert57286f92012-10-09 14:21:38 -070049 public static final int REASON_IS_SYNCABLE = -5;
Matthew Williamsfa774182013-06-18 15:44:11 -070050 /** Sync started because it has just been set to sync automatically. */
Alon Albert57286f92012-10-09 14:21:38 -070051 public static final int REASON_SYNC_AUTO = -6;
Matthew Williamsfa774182013-06-18 15:44:11 -070052 /** Sync started because master sync automatically has been set to true. */
Alon Albert57286f92012-10-09 14:21:38 -070053 public static final int REASON_MASTER_SYNC_AUTO = -7;
54 public static final int REASON_USER_START = -8;
55
56 private static String[] REASON_NAMES = new String[] {
57 "DataSettingsChanged",
58 "AccountsUpdated",
59 "ServiceChanged",
60 "Periodic",
61 "IsSyncable",
62 "AutoSync",
63 "MasterSyncAuto",
64 "UserStart",
65 };
66
Matthew Williams8ef22042013-07-26 12:56:39 -070067 /** Identifying info for the target for this operation. */
Matthew Williams56dbf8f2013-07-26 12:56:39 -070068 public final SyncStorageEngine.EndPoint target;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070069 public final int owningUid;
70 public final String owningPackage;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070071 /** Why this sync was kicked off. {@link #REASON_NAMES} */
Alon Albert57286f92012-10-09 14:21:38 -070072 public final int reason;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070073 /** Where this sync was initiated. */
Matthew Williams64280462014-01-09 10:49:23 -080074 public final int syncSource;
Fred Quintana0c4d04a2010-11-03 17:02:55 -070075 public final boolean allowParallelSyncs;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000076 public final Bundle extras;
77 public final boolean isPeriodic;
78 /** jobId of the periodic SyncOperation that initiated this one */
79 public final int sourcePeriodicId;
80 /** Operations are considered duplicates if keys are equal */
Fred Quintana307da1a2010-01-21 14:24:20 -080081 public final String key;
Fred Quintana307da1a2010-01-21 14:24:20 -080082
Shreyas Basarge8c834c02016-01-07 13:53:16 +000083 /** Poll frequency of periodic sync in milliseconds */
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +000084 public final long periodMillis;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000085 /** Flex time of periodic sync in milliseconds */
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +000086 public final long flexMillis;
Dianne Hackbornd45665b2014-02-26 12:35:32 -080087 /** Descriptive string key for this operation */
88 public String wakeLockName;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000089 /**
90 * Used when duplicate pending syncs are present. The one with the lowest expectedRuntime
91 * is kept, others are discarded.
92 */
93 public long expectedRuntime;
Dianne Hackbornd45665b2014-02-26 12:35:32 -080094
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +000095 /** Stores the number of times this sync operation failed and had to be retried. */
96 int retries;
97
Shreyas Basarge8c834c02016-01-07 13:53:16 +000098 /** jobId of the JobScheduler job corresponding to this sync */
99 public int jobId;
Amith Yamasani96a0fd652015-04-10 16:16:30 -0700100
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700101 public SyncOperation(Account account, int userId, int owningUid, String owningPackage,
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000102 int reason, int source, String provider, Bundle extras,
103 boolean allowParallelSyncs) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700104 this(new SyncStorageEngine.EndPoint(account, provider, userId), owningUid, owningPackage,
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000105 reason, source, extras, allowParallelSyncs);
Matthew Williams64280462014-01-09 10:49:23 -0800106 }
107
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700108 private SyncOperation(SyncStorageEngine.EndPoint info, int owningUid, String owningPackage,
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000109 int reason, int source, Bundle extras, boolean allowParallelSyncs) {
110 this(info, owningUid, owningPackage, reason, source, extras, allowParallelSyncs, false,
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000111 NO_JOB_ID, 0, 0);
112 }
113
114 public SyncOperation(SyncOperation op, long periodMillis, long flexMillis) {
115 this(op.target, op.owningUid, op.owningPackage, op.reason, op.syncSource,
116 new Bundle(op.extras), op.allowParallelSyncs, op.isPeriodic, op.sourcePeriodicId,
117 periodMillis, flexMillis);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000118 }
119
120 public SyncOperation(SyncStorageEngine.EndPoint info, int owningUid, String owningPackage,
121 int reason, int source, Bundle extras, boolean allowParallelSyncs,
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000122 boolean isPeriodic, int sourcePeriodicId, long periodMillis,
123 long flexMillis) {
Matthew Williams64280462014-01-09 10:49:23 -0800124 this.target = info;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700125 this.owningUid = owningUid;
126 this.owningPackage = owningPackage;
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700127 this.reason = reason;
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700128 this.syncSource = source;
Fred Quintana307da1a2010-01-21 14:24:20 -0800129 this.extras = new Bundle(extras);
Matthew Williams64280462014-01-09 10:49:23 -0800130 this.allowParallelSyncs = allowParallelSyncs;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000131 this.isPeriodic = isPeriodic;
132 this.sourcePeriodicId = sourcePeriodicId;
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000133 this.periodMillis = periodMillis;
134 this.flexMillis = flexMillis;
135 this.jobId = NO_JOB_ID;
136 this.key = toKey();
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000137 }
138
139 /* Get a one off sync operation instance from a periodic sync. */
140 public SyncOperation createOneTimeSyncOperation() {
141 if (!isPeriodic) {
142 return null;
Fred Quintana307da1a2010-01-21 14:24:20 -0800143 }
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000144 SyncOperation op = new SyncOperation(target, owningUid, owningPackage, reason, syncSource,
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000145 new Bundle(extras), allowParallelSyncs, false, jobId /* sourcePeriodicId */,
146 periodMillis, flexMillis);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000147 return op;
Fred Quintana307da1a2010-01-21 14:24:20 -0800148 }
149
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000150 public SyncOperation(SyncOperation other) {
151 target = other.target;
152 owningUid = other.owningUid;
153 owningPackage = other.owningPackage;
154 reason = other.reason;
155 syncSource = other.syncSource;
156 allowParallelSyncs = other.allowParallelSyncs;
157 extras = new Bundle(other.extras);
158 wakeLockName = other.wakeLockName();
159 isPeriodic = other.isPeriodic;
160 sourcePeriodicId = other.sourcePeriodicId;
161 periodMillis = other.periodMillis;
162 flexMillis = other.flexMillis;
163 this.key = other.key;
164 }
165
166 /**
167 * All fields are stored in a corresponding key in the persistable bundle.
168 *
169 * {@link #extras} is a Bundle and can contain parcelable objects. But only the type Account
170 * is allowed {@link ContentResolver#validateSyncExtrasBundle(Bundle)} that can't be stored in
171 * a PersistableBundle. For every value of type Account with key 'key', we store a
172 * PersistableBundle containing account information at key 'ACCOUNT:key'. The Account object
173 * can be reconstructed using this.
174 *
175 * We put a flag with key 'SyncManagerJob', to identify while reconstructing a sync operation
176 * from a bundle whether the bundle actually contains information about a sync.
177 * @return A persistable bundle containing all information to re-construct the sync operation.
178 */
179 PersistableBundle toJobInfoExtras() {
180 // This will be passed as extras bundle to a JobScheduler job.
181 PersistableBundle jobInfoExtras = new PersistableBundle();
182
183 PersistableBundle syncExtrasBundle = new PersistableBundle();
184 for (String key: extras.keySet()) {
185 Object value = extras.get(key);
186 if (value instanceof Account) {
187 Account account = (Account) value;
188 PersistableBundle accountBundle = new PersistableBundle();
189 accountBundle.putString("accountName", account.name);
190 accountBundle.putString("accountType", account.type);
191 // This is stored in jobInfoExtras so that we don't override a user specified
192 // sync extra with the same key.
193 jobInfoExtras.putPersistableBundle("ACCOUNT:" + key, accountBundle);
194 } else if (value instanceof Long) {
195 syncExtrasBundle.putLong(key, (Long) value);
196 } else if (value instanceof Integer) {
197 syncExtrasBundle.putInt(key, (Integer) value);
198 } else if (value instanceof Boolean) {
199 syncExtrasBundle.putBoolean(key, (Boolean) value);
200 } else if (value instanceof Float) {
Shreyas Basargeace6f6d2016-06-24 18:45:51 +0100201 syncExtrasBundle.putDouble(key, (double) (float) value);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000202 } else if (value instanceof Double) {
203 syncExtrasBundle.putDouble(key, (Double) value);
204 } else if (value instanceof String) {
205 syncExtrasBundle.putString(key, (String) value);
206 } else if (value == null) {
207 syncExtrasBundle.putString(key, null);
208 } else {
209 Slog.e(TAG, "Unknown extra type.");
210 }
211 }
212 jobInfoExtras.putPersistableBundle("syncExtras", syncExtrasBundle);
213
214 jobInfoExtras.putBoolean("SyncManagerJob", true);
215
216 jobInfoExtras.putString("provider", target.provider);
217 jobInfoExtras.putString("accountName", target.account.name);
218 jobInfoExtras.putString("accountType", target.account.type);
219 jobInfoExtras.putInt("userId", target.userId);
220 jobInfoExtras.putInt("owningUid", owningUid);
221 jobInfoExtras.putString("owningPackage", owningPackage);
222 jobInfoExtras.putInt("reason", reason);
223 jobInfoExtras.putInt("source", syncSource);
224 jobInfoExtras.putBoolean("allowParallelSyncs", allowParallelSyncs);
225 jobInfoExtras.putInt("jobId", jobId);
226 jobInfoExtras.putBoolean("isPeriodic", isPeriodic);
227 jobInfoExtras.putInt("sourcePeriodicId", sourcePeriodicId);
228 jobInfoExtras.putLong("periodMillis", periodMillis);
229 jobInfoExtras.putLong("flexMillis", flexMillis);
230 jobInfoExtras.putLong("expectedRuntime", expectedRuntime);
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000231 jobInfoExtras.putInt("retries", retries);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000232 return jobInfoExtras;
233 }
234
235 /**
236 * Reconstructs a sync operation from an extras Bundle. Returns null if the bundle doesn't
237 * contain a valid sync operation.
238 */
239 static SyncOperation maybeCreateFromJobExtras(PersistableBundle jobExtras) {
Makoto Onukia9dca242017-06-21 17:06:49 -0700240 if (jobExtras == null) {
241 return null;
242 }
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000243 String accountName, accountType;
244 String provider;
245 int userId, owningUid;
246 String owningPackage;
247 int reason, source;
248 int initiatedBy;
249 Bundle extras;
250 boolean allowParallelSyncs, isPeriodic;
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000251 long periodMillis, flexMillis;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000252
253 if (!jobExtras.getBoolean("SyncManagerJob", false)) {
254 return null;
255 }
256
257 accountName = jobExtras.getString("accountName");
258 accountType = jobExtras.getString("accountType");
259 provider = jobExtras.getString("provider");
260 userId = jobExtras.getInt("userId", Integer.MAX_VALUE);
261 owningUid = jobExtras.getInt("owningUid");
262 owningPackage = jobExtras.getString("owningPackage");
263 reason = jobExtras.getInt("reason", Integer.MAX_VALUE);
264 source = jobExtras.getInt("source", Integer.MAX_VALUE);
265 allowParallelSyncs = jobExtras.getBoolean("allowParallelSyncs", false);
266 isPeriodic = jobExtras.getBoolean("isPeriodic", false);
267 initiatedBy = jobExtras.getInt("sourcePeriodicId", NO_JOB_ID);
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000268 periodMillis = jobExtras.getLong("periodMillis");
269 flexMillis = jobExtras.getLong("flexMillis");
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000270 extras = new Bundle();
271
272 PersistableBundle syncExtras = jobExtras.getPersistableBundle("syncExtras");
273 if (syncExtras != null) {
274 extras.putAll(syncExtras);
275 }
276
277 for (String key: jobExtras.keySet()) {
278 if (key!= null && key.startsWith("ACCOUNT:")) {
279 String newKey = key.substring(8); // Strip off the 'ACCOUNT:' prefix.
280 PersistableBundle accountsBundle = jobExtras.getPersistableBundle(key);
281 Account account = new Account(accountsBundle.getString("accountName"),
282 accountsBundle.getString("accountType"));
283 extras.putParcelable(newKey, account);
284 }
285 }
286
287 Account account = new Account(accountName, accountType);
288 SyncStorageEngine.EndPoint target =
289 new SyncStorageEngine.EndPoint(account, provider, userId);
290 SyncOperation op = new SyncOperation(target, owningUid, owningPackage, reason, source,
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000291 extras, allowParallelSyncs, isPeriodic, initiatedBy, periodMillis, flexMillis);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000292 op.jobId = jobExtras.getInt("jobId");
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000293 op.expectedRuntime = jobExtras.getLong("expectedRuntime");
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000294 op.retries = jobExtras.getInt("retries");
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000295 return op;
Matthew Williamsfa774182013-06-18 15:44:11 -0700296 }
297
298 /**
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700299 * Determine whether if this sync operation is running, the provided operation would conflict
300 * with it.
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000301 * Parallel syncs allow multiple accounts to be synced at the same time.
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700302 */
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000303 boolean isConflict(SyncOperation toRun) {
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700304 final SyncStorageEngine.EndPoint other = toRun.target;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000305 return target.account.type.equals(other.account.type)
306 && target.provider.equals(other.provider)
307 && target.userId == other.userId
308 && (!allowParallelSyncs
309 || target.account.name.equals(other.account.name));
310 }
311
312 boolean isReasonPeriodic() {
313 return reason == REASON_PERIODIC;
314 }
315
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000316 boolean matchesPeriodicOperation(SyncOperation other) {
317 return target.matchesSpec(other.target)
318 && SyncManager.syncExtrasEquals(extras, other.extras, true)
319 && periodMillis == other.periodMillis && flexMillis == other.flexMillis;
320 }
321
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000322 boolean isDerivedFromFailedPeriodicSync() {
323 return sourcePeriodicId != NO_JOB_ID;
324 }
325
326 int findPriority() {
327 if (isInitialization()) {
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800328 return JobInfo.PRIORITY_SYNC_INITIALIZATION;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000329 } else if (isExpedited()) {
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800330 return JobInfo.PRIORITY_SYNC_EXPEDITED;
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700331 }
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800332 return JobInfo.PRIORITY_DEFAULT;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000333 }
334
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000335 private String toKey() {
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000336 StringBuilder sb = new StringBuilder();
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000337 sb.append("provider: ").append(target.provider);
338 sb.append(" account {name=" + target.account.name
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000339 + ", user="
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000340 + target.userId
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000341 + ", type="
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000342 + target.account.type
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000343 + "}");
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000344 sb.append(" isPeriodic: ").append(isPeriodic);
345 sb.append(" period: ").append(periodMillis);
346 sb.append(" flex: ").append(flexMillis);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000347 sb.append(" extras: ");
348 extrasToStringBuilder(extras, sb);
349 return sb.toString();
Fred Quintana307da1a2010-01-21 14:24:20 -0800350 }
351
Matthew Williamsfa774182013-06-18 15:44:11 -0700352 @Override
Fred Quintana307da1a2010-01-21 14:24:20 -0800353 public String toString() {
Alon Albert57286f92012-10-09 14:21:38 -0700354 return dump(null, true);
Fred Quintana918339a2010-10-05 14:00:39 -0700355 }
356
Makoto Onuki15e7a252017-06-08 17:12:05 -0700357 String dump(PackageManager pm, boolean shorter) {
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700358 StringBuilder sb = new StringBuilder();
Makoto Onuki15e7a252017-06-08 17:12:05 -0700359 sb.append("JobId=").append(jobId)
360 .append(" ")
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000361 .append(target.account.name)
Makoto Onuki15e7a252017-06-08 17:12:05 -0700362 .append("/")
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700363 .append(target.account.type)
Makoto Onuki15e7a252017-06-08 17:12:05 -0700364 .append(" u")
365 .append(target.userId)
366 .append(" [")
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700367 .append(target.provider)
Makoto Onuki15e7a252017-06-08 17:12:05 -0700368 .append("] ");
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000369 sb.append(SyncStorageEngine.SOURCES[syncSource]);
Makoto Onuki15e7a252017-06-08 17:12:05 -0700370 if (expectedRuntime != 0) {
371 sb.append(" ExpectedIn=");
372 SyncManager.formatDurationHMS(sb,
373 (expectedRuntime - SystemClock.elapsedRealtime()));
Fred Quintana918339a2010-10-05 14:00:39 -0700374 }
Makoto Onuki15e7a252017-06-08 17:12:05 -0700375 if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
376 sb.append(" EXPEDITED");
377 }
378 sb.append(" Reason=");
Alon Albert57286f92012-10-09 14:21:38 -0700379 sb.append(reasonToString(pm, reason));
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000380 if (isPeriodic) {
Makoto Onuki15e7a252017-06-08 17:12:05 -0700381 sb.append(" (period=");
382 SyncManager.formatDurationHMS(sb, periodMillis);
383 sb.append(" flex=");
384 SyncManager.formatDurationHMS(sb, flexMillis);
385 sb.append(")");
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000386 }
Makoto Onuki15e7a252017-06-08 17:12:05 -0700387 if (!shorter) {
388 sb.append(" Owner={");
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700389 UserHandle.formatUid(sb, owningUid);
Makoto Onuki15e7a252017-06-08 17:12:05 -0700390 sb.append(" ");
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700391 sb.append(owningPackage);
Makoto Onuki15e7a252017-06-08 17:12:05 -0700392 sb.append("}");
393 if (!extras.keySet().isEmpty()) {
394 sb.append(" ");
395 extrasToStringBuilder(extras, sb);
396 }
Fred Quintana918339a2010-10-05 14:00:39 -0700397 }
Fred Quintana307da1a2010-01-21 14:24:20 -0800398 return sb.toString();
399 }
400
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000401 static String reasonToString(PackageManager pm, int reason) {
Alon Albert57286f92012-10-09 14:21:38 -0700402 if (reason >= 0) {
403 if (pm != null) {
404 final String[] packages = pm.getPackagesForUid(reason);
405 if (packages != null && packages.length == 1) {
406 return packages[0];
407 }
408 final String name = pm.getNameForUid(reason);
409 if (name != null) {
410 return name;
411 }
412 return String.valueOf(reason);
413 } else {
414 return String.valueOf(reason);
415 }
416 } else {
417 final int index = -reason - 1;
418 if (index >= REASON_NAMES.length) {
419 return String.valueOf(reason);
420 } else {
421 return REASON_NAMES[index];
422 }
423 }
424 }
425
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000426 boolean isInitialization() {
Fred Quintana918339a2010-10-05 14:00:39 -0700427 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
428 }
429
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000430 boolean isExpedited() {
431 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
Fred Quintanadc475562012-05-04 15:51:54 -0700432 }
433
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000434 boolean ignoreBackoff() {
Fred Quintana918339a2010-10-05 14:00:39 -0700435 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false);
436 }
437
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000438 boolean isNotAllowedOnMetered() {
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700439 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
440 }
441
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000442 boolean isManual() {
Matthew Williams92a1c092014-08-25 19:18:32 -0700443 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
444 }
445
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000446 boolean isIgnoreSettings() {
Matthew Williams92a1c092014-08-25 19:18:32 -0700447 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
448 }
449
Makoto Onuki15e7a252017-06-08 17:12:05 -0700450 static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
Makoto Onukia9dca242017-06-21 17:06:49 -0700451 if (bundle == null) {
452 sb.append("null");
453 return;
454 }
Fred Quintana307da1a2010-01-21 14:24:20 -0800455 sb.append("[");
456 for (String key : bundle.keySet()) {
Fred Quintana307da1a2010-01-21 14:24:20 -0800457 sb.append(key).append("=").append(bundle.get(key)).append(" ");
458 }
459 sb.append("]");
460 }
461
Makoto Onukia9dca242017-06-21 17:06:49 -0700462 static String extrasToString(Bundle bundle) {
463 final StringBuilder sb = new StringBuilder();
464 extrasToStringBuilder(bundle, sb);
465 return sb.toString();
466 }
467
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000468 String wakeLockName() {
Dianne Hackbornd45665b2014-02-26 12:35:32 -0800469 if (wakeLockName != null) {
470 return wakeLockName;
471 }
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000472 return (wakeLockName = target.provider
473 + "/" + target.account.type
474 + "/" + target.account.name);
Fred Quintana307da1a2010-01-21 14:24:20 -0800475 }
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700476
477 // TODO: Test this to make sure that casting to object doesn't lose the type info for EventLog.
478 public Object[] toEventLog(int event) {
479 Object[] logArray = new Object[4];
480 logArray[1] = event;
481 logArray[2] = syncSource;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000482 logArray[0] = target.provider;
483 logArray[3] = target.account.name.hashCode();
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700484 return logArray;
485 }
Fred Quintana307da1a2010-01-21 14:24:20 -0800486}