blob: c371f9705285b6817a3b54c4db981c598e64e10f [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;
Alon Albert57286f92012-10-09 14:21:38 -070021import android.content.pm.PackageManager;
Jeff Sharkey7a96c392012-11-15 14:01:46 -080022import android.content.ContentResolver;
Fred Quintana307da1a2010-01-21 14:24:20 -080023import android.os.Bundle;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000024import android.os.PersistableBundle;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070025import android.os.UserHandle;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000026import android.util.Slog;
Fred Quintana307da1a2010-01-21 14:24:20 -080027
28/**
29 * Value type that represents a sync operation.
Shreyas Basarge8c834c02016-01-07 13:53:16 +000030 * This holds all information related to a sync operation - both one off and periodic.
31 * Data stored in this is used to schedule a job with the JobScheduler.
Matthew Williamsfa774182013-06-18 15:44:11 -070032 * {@hide}
Fred Quintana307da1a2010-01-21 14:24:20 -080033 */
Shreyas Basarge8c834c02016-01-07 13:53:16 +000034public class SyncOperation {
Matthew Williams56dbf8f2013-07-26 12:56:39 -070035 public static final String TAG = "SyncManager";
36
Shreyas Basarge8c834c02016-01-07 13:53:16 +000037 /**
38 * This is used in the {@link #sourcePeriodicId} field if the operation is not initiated by a failed
39 * periodic sync.
40 */
41 public static final int NO_JOB_ID = -1;
42
Alon Albert57286f92012-10-09 14:21:38 -070043 public static final int REASON_BACKGROUND_DATA_SETTINGS_CHANGED = -1;
44 public static final int REASON_ACCOUNTS_UPDATED = -2;
45 public static final int REASON_SERVICE_CHANGED = -3;
46 public static final int REASON_PERIODIC = -4;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070047 /** Sync started because it has just been set to isSyncable. */
Alon Albert57286f92012-10-09 14:21:38 -070048 public static final int REASON_IS_SYNCABLE = -5;
Matthew Williamsfa774182013-06-18 15:44:11 -070049 /** Sync started because it has just been set to sync automatically. */
Alon Albert57286f92012-10-09 14:21:38 -070050 public static final int REASON_SYNC_AUTO = -6;
Matthew Williamsfa774182013-06-18 15:44:11 -070051 /** Sync started because master sync automatically has been set to true. */
Alon Albert57286f92012-10-09 14:21:38 -070052 public static final int REASON_MASTER_SYNC_AUTO = -7;
53 public static final int REASON_USER_START = -8;
54
55 private static String[] REASON_NAMES = new String[] {
56 "DataSettingsChanged",
57 "AccountsUpdated",
58 "ServiceChanged",
59 "Periodic",
60 "IsSyncable",
61 "AutoSync",
62 "MasterSyncAuto",
63 "UserStart",
64 };
65
Matthew Williams8ef22042013-07-26 12:56:39 -070066 /** Identifying info for the target for this operation. */
Matthew Williams56dbf8f2013-07-26 12:56:39 -070067 public final SyncStorageEngine.EndPoint target;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -070068 public final int owningUid;
69 public final String owningPackage;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070070 /** Why this sync was kicked off. {@link #REASON_NAMES} */
Alon Albert57286f92012-10-09 14:21:38 -070071 public final int reason;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070072 /** Where this sync was initiated. */
Matthew Williams64280462014-01-09 10:49:23 -080073 public final int syncSource;
Fred Quintana0c4d04a2010-11-03 17:02:55 -070074 public final boolean allowParallelSyncs;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000075 public final Bundle extras;
76 public final boolean isPeriodic;
77 /** jobId of the periodic SyncOperation that initiated this one */
78 public final int sourcePeriodicId;
79 /** Operations are considered duplicates if keys are equal */
Fred Quintana307da1a2010-01-21 14:24:20 -080080 public final String key;
Fred Quintana307da1a2010-01-21 14:24:20 -080081
Shreyas Basarge8c834c02016-01-07 13:53:16 +000082 /** Poll frequency of periodic sync in milliseconds */
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +000083 public final long periodMillis;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000084 /** Flex time of periodic sync in milliseconds */
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +000085 public final long flexMillis;
Dianne Hackbornd45665b2014-02-26 12:35:32 -080086 /** Descriptive string key for this operation */
87 public String wakeLockName;
Shreyas Basarge8c834c02016-01-07 13:53:16 +000088 /**
89 * Used when duplicate pending syncs are present. The one with the lowest expectedRuntime
90 * is kept, others are discarded.
91 */
92 public long expectedRuntime;
Dianne Hackbornd45665b2014-02-26 12:35:32 -080093
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +000094 /** Stores the number of times this sync operation failed and had to be retried. */
95 int retries;
96
Shreyas Basarge8c834c02016-01-07 13:53:16 +000097 /** jobId of the JobScheduler job corresponding to this sync */
98 public int jobId;
Amith Yamasani96a0fd652015-04-10 16:16:30 -070099
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700100 public SyncOperation(Account account, int userId, int owningUid, String owningPackage,
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000101 int reason, int source, String provider, Bundle extras,
102 boolean allowParallelSyncs) {
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700103 this(new SyncStorageEngine.EndPoint(account, provider, userId), owningUid, owningPackage,
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000104 reason, source, extras, allowParallelSyncs);
Matthew Williams64280462014-01-09 10:49:23 -0800105 }
106
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700107 private SyncOperation(SyncStorageEngine.EndPoint info, int owningUid, String owningPackage,
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000108 int reason, int source, Bundle extras, boolean allowParallelSyncs) {
109 this(info, owningUid, owningPackage, reason, source, extras, allowParallelSyncs, false,
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000110 NO_JOB_ID, 0, 0);
111 }
112
113 public SyncOperation(SyncOperation op, long periodMillis, long flexMillis) {
114 this(op.target, op.owningUid, op.owningPackage, op.reason, op.syncSource,
115 new Bundle(op.extras), op.allowParallelSyncs, op.isPeriodic, op.sourcePeriodicId,
116 periodMillis, flexMillis);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000117 }
118
119 public SyncOperation(SyncStorageEngine.EndPoint info, int owningUid, String owningPackage,
120 int reason, int source, Bundle extras, boolean allowParallelSyncs,
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000121 boolean isPeriodic, int sourcePeriodicId, long periodMillis,
122 long flexMillis) {
Matthew Williams64280462014-01-09 10:49:23 -0800123 this.target = info;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700124 this.owningUid = owningUid;
125 this.owningPackage = owningPackage;
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700126 this.reason = reason;
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700127 this.syncSource = source;
Fred Quintana307da1a2010-01-21 14:24:20 -0800128 this.extras = new Bundle(extras);
Matthew Williams64280462014-01-09 10:49:23 -0800129 this.allowParallelSyncs = allowParallelSyncs;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000130 this.isPeriodic = isPeriodic;
131 this.sourcePeriodicId = sourcePeriodicId;
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000132 this.periodMillis = periodMillis;
133 this.flexMillis = flexMillis;
134 this.jobId = NO_JOB_ID;
135 this.key = toKey();
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000136 }
137
138 /* Get a one off sync operation instance from a periodic sync. */
139 public SyncOperation createOneTimeSyncOperation() {
140 if (!isPeriodic) {
141 return null;
Fred Quintana307da1a2010-01-21 14:24:20 -0800142 }
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000143 SyncOperation op = new SyncOperation(target, owningUid, owningPackage, reason, syncSource,
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000144 new Bundle(extras), allowParallelSyncs, false, jobId /* sourcePeriodicId */,
145 periodMillis, flexMillis);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000146 return op;
Fred Quintana307da1a2010-01-21 14:24:20 -0800147 }
148
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000149 public SyncOperation(SyncOperation other) {
150 target = other.target;
151 owningUid = other.owningUid;
152 owningPackage = other.owningPackage;
153 reason = other.reason;
154 syncSource = other.syncSource;
155 allowParallelSyncs = other.allowParallelSyncs;
156 extras = new Bundle(other.extras);
157 wakeLockName = other.wakeLockName();
158 isPeriodic = other.isPeriodic;
159 sourcePeriodicId = other.sourcePeriodicId;
160 periodMillis = other.periodMillis;
161 flexMillis = other.flexMillis;
162 this.key = other.key;
163 }
164
165 /**
166 * All fields are stored in a corresponding key in the persistable bundle.
167 *
168 * {@link #extras} is a Bundle and can contain parcelable objects. But only the type Account
169 * is allowed {@link ContentResolver#validateSyncExtrasBundle(Bundle)} that can't be stored in
170 * a PersistableBundle. For every value of type Account with key 'key', we store a
171 * PersistableBundle containing account information at key 'ACCOUNT:key'. The Account object
172 * can be reconstructed using this.
173 *
174 * We put a flag with key 'SyncManagerJob', to identify while reconstructing a sync operation
175 * from a bundle whether the bundle actually contains information about a sync.
176 * @return A persistable bundle containing all information to re-construct the sync operation.
177 */
178 PersistableBundle toJobInfoExtras() {
179 // This will be passed as extras bundle to a JobScheduler job.
180 PersistableBundle jobInfoExtras = new PersistableBundle();
181
182 PersistableBundle syncExtrasBundle = new PersistableBundle();
183 for (String key: extras.keySet()) {
184 Object value = extras.get(key);
185 if (value instanceof Account) {
186 Account account = (Account) value;
187 PersistableBundle accountBundle = new PersistableBundle();
188 accountBundle.putString("accountName", account.name);
189 accountBundle.putString("accountType", account.type);
190 // This is stored in jobInfoExtras so that we don't override a user specified
191 // sync extra with the same key.
192 jobInfoExtras.putPersistableBundle("ACCOUNT:" + key, accountBundle);
193 } else if (value instanceof Long) {
194 syncExtrasBundle.putLong(key, (Long) value);
195 } else if (value instanceof Integer) {
196 syncExtrasBundle.putInt(key, (Integer) value);
197 } else if (value instanceof Boolean) {
198 syncExtrasBundle.putBoolean(key, (Boolean) value);
199 } else if (value instanceof Float) {
Shreyas Basargeace6f6d2016-06-24 18:45:51 +0100200 syncExtrasBundle.putDouble(key, (double) (float) value);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000201 } else if (value instanceof Double) {
202 syncExtrasBundle.putDouble(key, (Double) value);
203 } else if (value instanceof String) {
204 syncExtrasBundle.putString(key, (String) value);
205 } else if (value == null) {
206 syncExtrasBundle.putString(key, null);
207 } else {
208 Slog.e(TAG, "Unknown extra type.");
209 }
210 }
211 jobInfoExtras.putPersistableBundle("syncExtras", syncExtrasBundle);
212
213 jobInfoExtras.putBoolean("SyncManagerJob", true);
214
215 jobInfoExtras.putString("provider", target.provider);
216 jobInfoExtras.putString("accountName", target.account.name);
217 jobInfoExtras.putString("accountType", target.account.type);
218 jobInfoExtras.putInt("userId", target.userId);
219 jobInfoExtras.putInt("owningUid", owningUid);
220 jobInfoExtras.putString("owningPackage", owningPackage);
221 jobInfoExtras.putInt("reason", reason);
222 jobInfoExtras.putInt("source", syncSource);
223 jobInfoExtras.putBoolean("allowParallelSyncs", allowParallelSyncs);
224 jobInfoExtras.putInt("jobId", jobId);
225 jobInfoExtras.putBoolean("isPeriodic", isPeriodic);
226 jobInfoExtras.putInt("sourcePeriodicId", sourcePeriodicId);
227 jobInfoExtras.putLong("periodMillis", periodMillis);
228 jobInfoExtras.putLong("flexMillis", flexMillis);
229 jobInfoExtras.putLong("expectedRuntime", expectedRuntime);
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000230 jobInfoExtras.putInt("retries", retries);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000231 return jobInfoExtras;
232 }
233
234 /**
235 * Reconstructs a sync operation from an extras Bundle. Returns null if the bundle doesn't
236 * contain a valid sync operation.
237 */
238 static SyncOperation maybeCreateFromJobExtras(PersistableBundle jobExtras) {
239 String accountName, accountType;
240 String provider;
241 int userId, owningUid;
242 String owningPackage;
243 int reason, source;
244 int initiatedBy;
245 Bundle extras;
246 boolean allowParallelSyncs, isPeriodic;
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000247 long periodMillis, flexMillis;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000248
249 if (!jobExtras.getBoolean("SyncManagerJob", false)) {
250 return null;
251 }
252
253 accountName = jobExtras.getString("accountName");
254 accountType = jobExtras.getString("accountType");
255 provider = jobExtras.getString("provider");
256 userId = jobExtras.getInt("userId", Integer.MAX_VALUE);
257 owningUid = jobExtras.getInt("owningUid");
258 owningPackage = jobExtras.getString("owningPackage");
259 reason = jobExtras.getInt("reason", Integer.MAX_VALUE);
260 source = jobExtras.getInt("source", Integer.MAX_VALUE);
261 allowParallelSyncs = jobExtras.getBoolean("allowParallelSyncs", false);
262 isPeriodic = jobExtras.getBoolean("isPeriodic", false);
263 initiatedBy = jobExtras.getInt("sourcePeriodicId", NO_JOB_ID);
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000264 periodMillis = jobExtras.getLong("periodMillis");
265 flexMillis = jobExtras.getLong("flexMillis");
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000266 extras = new Bundle();
267
268 PersistableBundle syncExtras = jobExtras.getPersistableBundle("syncExtras");
269 if (syncExtras != null) {
270 extras.putAll(syncExtras);
271 }
272
273 for (String key: jobExtras.keySet()) {
274 if (key!= null && key.startsWith("ACCOUNT:")) {
275 String newKey = key.substring(8); // Strip off the 'ACCOUNT:' prefix.
276 PersistableBundle accountsBundle = jobExtras.getPersistableBundle(key);
277 Account account = new Account(accountsBundle.getString("accountName"),
278 accountsBundle.getString("accountType"));
279 extras.putParcelable(newKey, account);
280 }
281 }
282
283 Account account = new Account(accountName, accountType);
284 SyncStorageEngine.EndPoint target =
285 new SyncStorageEngine.EndPoint(account, provider, userId);
286 SyncOperation op = new SyncOperation(target, owningUid, owningPackage, reason, source,
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000287 extras, allowParallelSyncs, isPeriodic, initiatedBy, periodMillis, flexMillis);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000288 op.jobId = jobExtras.getInt("jobId");
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000289 op.expectedRuntime = jobExtras.getLong("expectedRuntime");
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000290 op.retries = jobExtras.getInt("retries");
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000291 return op;
Matthew Williamsfa774182013-06-18 15:44:11 -0700292 }
293
294 /**
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700295 * Determine whether if this sync operation is running, the provided operation would conflict
296 * with it.
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000297 * Parallel syncs allow multiple accounts to be synced at the same time.
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700298 */
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000299 boolean isConflict(SyncOperation toRun) {
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700300 final SyncStorageEngine.EndPoint other = toRun.target;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000301 return target.account.type.equals(other.account.type)
302 && target.provider.equals(other.provider)
303 && target.userId == other.userId
304 && (!allowParallelSyncs
305 || target.account.name.equals(other.account.name));
306 }
307
308 boolean isReasonPeriodic() {
309 return reason == REASON_PERIODIC;
310 }
311
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000312 boolean matchesPeriodicOperation(SyncOperation other) {
313 return target.matchesSpec(other.target)
314 && SyncManager.syncExtrasEquals(extras, other.extras, true)
315 && periodMillis == other.periodMillis && flexMillis == other.flexMillis;
316 }
317
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000318 boolean isDerivedFromFailedPeriodicSync() {
319 return sourcePeriodicId != NO_JOB_ID;
320 }
321
322 int findPriority() {
323 if (isInitialization()) {
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800324 return JobInfo.PRIORITY_SYNC_INITIALIZATION;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000325 } else if (isExpedited()) {
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800326 return JobInfo.PRIORITY_SYNC_EXPEDITED;
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700327 }
Dianne Hackborn1085ff62016-02-23 17:04:58 -0800328 return JobInfo.PRIORITY_DEFAULT;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000329 }
330
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000331 private String toKey() {
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000332 StringBuilder sb = new StringBuilder();
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000333 sb.append("provider: ").append(target.provider);
334 sb.append(" account {name=" + target.account.name
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000335 + ", user="
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000336 + target.userId
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000337 + ", type="
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000338 + target.account.type
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000339 + "}");
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000340 sb.append(" isPeriodic: ").append(isPeriodic);
341 sb.append(" period: ").append(periodMillis);
342 sb.append(" flex: ").append(flexMillis);
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000343 sb.append(" extras: ");
344 extrasToStringBuilder(extras, sb);
345 return sb.toString();
Fred Quintana307da1a2010-01-21 14:24:20 -0800346 }
347
Matthew Williamsfa774182013-06-18 15:44:11 -0700348 @Override
Fred Quintana307da1a2010-01-21 14:24:20 -0800349 public String toString() {
Alon Albert57286f92012-10-09 14:21:38 -0700350 return dump(null, true);
Fred Quintana918339a2010-10-05 14:00:39 -0700351 }
352
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000353 String dump(PackageManager pm, boolean useOneLine) {
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700354 StringBuilder sb = new StringBuilder();
Shreyas Basarge2b4c8f92016-02-08 23:52:27 +0000355 sb.append("JobId: ").append(jobId)
356 .append(", ")
357 .append(target.account.name)
Alon Albert8e285552012-09-17 15:05:27 -0700358 .append(" u")
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700359 .append(target.userId).append(" (")
360 .append(target.account.type)
Alon Albert8e285552012-09-17 15:05:27 -0700361 .append(")")
362 .append(", ")
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700363 .append(target.provider)
364 .append(", ");
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000365 sb.append(SyncStorageEngine.SOURCES[syncSource]);
366 if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
Fred Quintana918339a2010-10-05 14:00:39 -0700367 sb.append(", EXPEDITED");
368 }
Alon Albert57286f92012-10-09 14:21:38 -0700369 sb.append(", reason: ");
370 sb.append(reasonToString(pm, reason));
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000371 if (isPeriodic) {
372 sb.append(", period: " + periodMillis).append(", flexMillis: " + flexMillis);
373 }
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700374 if (!useOneLine) {
375 sb.append("\n ");
376 sb.append("owningUid=");
377 UserHandle.formatUid(sb, owningUid);
378 sb.append(" owningPackage=");
379 sb.append(owningPackage);
380 }
Fred Quintana918339a2010-10-05 14:00:39 -0700381 if (!useOneLine && !extras.keySet().isEmpty()) {
382 sb.append("\n ");
383 extrasToStringBuilder(extras, sb);
384 }
Fred Quintana307da1a2010-01-21 14:24:20 -0800385 return sb.toString();
386 }
387
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000388 static String reasonToString(PackageManager pm, int reason) {
Alon Albert57286f92012-10-09 14:21:38 -0700389 if (reason >= 0) {
390 if (pm != null) {
391 final String[] packages = pm.getPackagesForUid(reason);
392 if (packages != null && packages.length == 1) {
393 return packages[0];
394 }
395 final String name = pm.getNameForUid(reason);
396 if (name != null) {
397 return name;
398 }
399 return String.valueOf(reason);
400 } else {
401 return String.valueOf(reason);
402 }
403 } else {
404 final int index = -reason - 1;
405 if (index >= REASON_NAMES.length) {
406 return String.valueOf(reason);
407 } else {
408 return REASON_NAMES[index];
409 }
410 }
411 }
412
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000413 boolean isInitialization() {
Fred Quintana918339a2010-10-05 14:00:39 -0700414 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
415 }
416
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000417 boolean isExpedited() {
418 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
Fred Quintanadc475562012-05-04 15:51:54 -0700419 }
420
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000421 boolean ignoreBackoff() {
Fred Quintana918339a2010-10-05 14:00:39 -0700422 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false);
423 }
424
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000425 boolean isNotAllowedOnMetered() {
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700426 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
427 }
428
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000429 boolean isManual() {
Matthew Williams92a1c092014-08-25 19:18:32 -0700430 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
431 }
432
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000433 boolean isIgnoreSettings() {
Matthew Williams92a1c092014-08-25 19:18:32 -0700434 return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
435 }
436
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700437 private static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
Fred Quintana307da1a2010-01-21 14:24:20 -0800438 sb.append("[");
439 for (String key : bundle.keySet()) {
Fred Quintana307da1a2010-01-21 14:24:20 -0800440 sb.append(key).append("=").append(bundle.get(key)).append(" ");
441 }
442 sb.append("]");
443 }
444
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000445 String wakeLockName() {
Dianne Hackbornd45665b2014-02-26 12:35:32 -0800446 if (wakeLockName != null) {
447 return wakeLockName;
448 }
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000449 return (wakeLockName = target.provider
450 + "/" + target.account.type
451 + "/" + target.account.name);
Fred Quintana307da1a2010-01-21 14:24:20 -0800452 }
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700453
454 // TODO: Test this to make sure that casting to object doesn't lose the type info for EventLog.
455 public Object[] toEventLog(int event) {
456 Object[] logArray = new Object[4];
457 logArray[1] = event;
458 logArray[2] = syncSource;
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000459 logArray[0] = target.provider;
460 logArray[3] = target.account.name.hashCode();
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700461 return logArray;
462 }
Fred Quintana307da1a2010-01-21 14:24:20 -0800463}