115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root/*
215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Copyright (C) 2010 The Android Open Source Project
315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root *
415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * you may not use this file except in compliance with the License.
615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * You may obtain a copy of the License at
715a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root *
815a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
915a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root *
1015a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Unless required by applicable law or agreed to in writing, software
1115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
1215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * See the License for the specific language governing permissions and
1415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * limitations under the License.
1515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root */
1615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root
177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.android.server.content;
18307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
19307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanaimport android.accounts.Account;
2057286f970641493b315b0b42aba7ac6b672cc8b8Alon Albertimport android.content.pm.PackageManager;
21fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williamsimport android.content.ComponentName;
227a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.ContentResolver;
23307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanaimport android.os.Bundle;
24307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanaimport android.os.SystemClock;
2556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williamsimport android.util.Log;
26307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
27307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana/**
28307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana * Value type that represents a sync operation.
29fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * TODO: This is the class to flesh out with all the scheduling data - metered/unmetered,
30fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * transfer-size, etc.
31fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * {@hide}
32307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana */
33307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanapublic class SyncOperation implements Comparable {
3456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static final String TAG = "SyncManager";
3556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
3657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public static final int REASON_BACKGROUND_DATA_SETTINGS_CHANGED = -1;
3757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public static final int REASON_ACCOUNTS_UPDATED = -2;
3857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public static final int REASON_SERVICE_CHANGED = -3;
3957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public static final int REASON_PERIODIC = -4;
4056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /** Sync started because it has just been set to isSyncable. */
4157286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public static final int REASON_IS_SYNCABLE = -5;
42fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** Sync started because it has just been set to sync automatically. */
4357286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public static final int REASON_SYNC_AUTO = -6;
44fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** Sync started because master sync automatically has been set to true. */
4557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public static final int REASON_MASTER_SYNC_AUTO = -7;
4657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public static final int REASON_USER_START = -8;
4757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert
4857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    private static String[] REASON_NAMES = new String[] {
4957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            "DataSettingsChanged",
5057286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            "AccountsUpdated",
5157286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            "ServiceChanged",
5257286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            "Periodic",
5357286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            "IsSyncable",
5457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            "AutoSync",
5557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            "MasterSyncAuto",
5657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            "UserStart",
5757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    };
5857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert
5956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static final int SYNC_TARGET_UNKNOWN = 0;
6056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static final int SYNC_TARGET_ADAPTER = 1;
6156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static final int SYNC_TARGET_SERVICE = 2;
6256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
638ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams    /** Identifying info for the target for this operation. */
6456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public final SyncStorageEngine.EndPoint target;
6556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /** Why this sync was kicked off. {@link #REASON_NAMES} */
6657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public final int reason;
6756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /** Where this sync was initiated. */
686428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams    public final int syncSource;
690c4d04ac2e8aa62560d8d767fa1c87e5361b0b08Fred Quintana    public final boolean allowParallelSyncs;
70307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public final String key;
716428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams    /** Internal boolean to avoid reading a bundle everytime we want to compare operations. */
726428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams    private final boolean expedited;
736428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams    public Bundle extras;
7456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /** Bare-bones version of this operation that is persisted across reboots. */
75307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public SyncStorageEngine.PendingOperation pendingOperation;
76fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** Elapsed real time in millis at which to run this sync. */
77fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    public long latestRunTime;
78fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** Set by the SyncManager in order to delay retries. */
796428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams    public long backoff;
80fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** Specified by the adapter to delay subsequent sync operations. */
81918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    public long delayUntil;
82fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
83fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * Elapsed real time in millis when this sync will be run.
84fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * Depends on max(backoff, latestRunTime, and delayUntil).
85fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
86918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    public long effectiveRunTime;
8756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /** Amount of time before {@link #effectiveRunTime} from which this sync can run. */
88fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    public long flexTime;
89307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
90d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn    /** Descriptive string key for this operation */
91d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn    public String wakeLockName;
92d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn
9356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public SyncOperation(Account account, int userId, int reason, int source, String provider,
94fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            Bundle extras, long runTimeFromNow, long flexTime, long backoff,
95fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            long delayUntil, boolean allowParallelSyncs) {
966428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        this(new SyncStorageEngine.EndPoint(account, provider, userId),
976428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                reason, source, extras, runTimeFromNow, flexTime, backoff, delayUntil,
986428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                allowParallelSyncs);
9956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
10056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
10156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public SyncOperation(ComponentName service, int userId, int reason, int source,
10256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            Bundle extras, long runTimeFromNow, long flexTime, long backoff,
10356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            long delayUntil) {
1046428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        this(new SyncStorageEngine.EndPoint(service, userId), reason, source, extras,
1056428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                runTimeFromNow, flexTime, backoff, delayUntil, true /* allowParallelSyncs */);
10656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
10756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
1086428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams    private SyncOperation(SyncStorageEngine.EndPoint info, int reason, int source, Bundle extras,
1096428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams            long runTimeFromNow, long flexTime, long backoff, long delayUntil,
1106428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams            boolean allowParallelSyncs) {
1116428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        this.target = info;
1126428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        this.reason = reason;
11356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        this.syncSource = source;
114307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        this.extras = new Bundle(extras);
115fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        cleanBundle(this.extras);
116918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        this.delayUntil = delayUntil;
117918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        this.backoff = backoff;
1186428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        this.allowParallelSyncs = allowParallelSyncs;
119307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        final long now = SystemClock.elapsedRealtime();
1206428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        // Set expedited based on runTimeFromNow. The SyncManager specifies whether the op is
1216428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        // expedited (Not done solely based on bundle).
1226428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        if (runTimeFromNow < 0) {
123307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            this.expedited = true;
1246428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams            // Sanity check: Will always be true.
1256428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams            if (!this.extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
1266428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                this.extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
1276428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams            }
128fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            this.latestRunTime = now;
129fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            this.flexTime = 0;
130307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        } else {
131307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            this.expedited = false;
1326428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams            this.extras.remove(ContentResolver.SYNC_EXTRAS_EXPEDITED);
133fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            this.latestRunTime = now + runTimeFromNow;
134fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            this.flexTime = flexTime;
135307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
136918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        updateEffectiveRunTime();
1376428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        this.key = toKey(info, this.extras);
1386428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams    }
1396428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams
1406428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams    /** Used to reschedule a sync at a new point in time. */
1416428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams    public SyncOperation(SyncOperation other, long newRunTimeFromNow) {
1426428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        this(other.target, other.reason, other.syncSource, new Bundle(other.extras),
1436428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                newRunTimeFromNow,
1446428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                0L /* In back-off so no flex */,
1456428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                other.backoff,
1466428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                other.delayUntil,
1476428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                other.allowParallelSyncs);
148307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
149307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
15056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public boolean matchesAuthority(SyncOperation other) {
1518ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        return this.target.matchesSpec(other.target);
152307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
153307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
154fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
155fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * Make sure the bundle attached to this SyncOperation doesn't have unnecessary
156fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * flags set.
157fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * @param bundle to clean.
158fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
159fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    private void cleanBundle(Bundle bundle) {
160fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_UPLOAD);
161fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_MANUAL);
162fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS);
163fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF);
164fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY);
165fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS);
166fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_EXPEDITED);
167fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS);
16856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        removeFalseExtra(bundle, ContentResolver.SYNC_EXTRAS_DISALLOW_METERED);
169fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    }
170fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
171fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    private void removeFalseExtra(Bundle bundle, String extraName) {
172fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        if (!bundle.getBoolean(extraName, false)) {
173fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            bundle.remove(extraName);
174fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        }
175fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    }
176fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
17756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /**
17856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * Determine whether if this sync operation is running, the provided operation would conflict
17956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * with it.
18056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * Parallel syncs allow multiple accounts to be synced at the same time.
18156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     */
18256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public boolean isConflict(SyncOperation toRun) {
18356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        final SyncStorageEngine.EndPoint other = toRun.target;
18456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (target.target_provider) {
18556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return target.account.type.equals(other.account.type)
18656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    && target.provider.equals(other.provider)
18756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    && target.userId == other.userId
18856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    && (!allowParallelSyncs
18956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            || target.account.name.equals(other.account.name));
19056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else {
19156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            // Ops that target a service default to allow parallel syncs, which is handled by the
19256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            // service returning SYNC_IN_PROGRESS if they don't.
19356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return target.service.equals(other.service) && !allowParallelSyncs;
19456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
195307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
196307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
197fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    @Override
198307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public String toString() {
19957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        return dump(null, true);
200918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    }
201918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana
20257286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public String dump(PackageManager pm, boolean useOneLine) {
20356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        StringBuilder sb = new StringBuilder();
20456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (target.target_provider) {
20556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            sb.append(target.account.name)
2068e28555f6d4ea557ba79e3d411ea46e5a0788b8fAlon Albert                .append(" u")
20756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(target.userId).append(" (")
20856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(target.account.type)
2098e28555f6d4ea557ba79e3d411ea46e5a0788b8fAlon Albert                .append(")")
2108e28555f6d4ea557ba79e3d411ea46e5a0788b8fAlon Albert                .append(", ")
21156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(target.provider)
21256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(", ");
21356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else if (target.target_service) {
21456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            sb.append(target.service.getPackageName())
21556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(" u")
21656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(target.userId).append(" (")
21756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(target.service.getClassName()).append(")")
21856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(", ");
21956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
22056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        sb.append(SyncStorageEngine.SOURCES[syncSource])
22156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            .append(", currentRunTime ")
22256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            .append(effectiveRunTime);
223918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        if (expedited) {
224918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana            sb.append(", EXPEDITED");
225918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        }
22657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        sb.append(", reason: ");
22757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        sb.append(reasonToString(pm, reason));
228918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        if (!useOneLine && !extras.keySet().isEmpty()) {
229918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana            sb.append("\n    ");
230918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana            extrasToStringBuilder(extras, sb);
231918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        }
232307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        return sb.toString();
233307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
234307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
23557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    public static String reasonToString(PackageManager pm, int reason) {
23657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        if (reason >= 0) {
23757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            if (pm != null) {
23857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                final String[] packages = pm.getPackagesForUid(reason);
23957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                if (packages != null && packages.length == 1) {
24057286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                    return packages[0];
24157286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                }
24257286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                final String name = pm.getNameForUid(reason);
24357286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                if (name != null) {
24457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                    return name;
24557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                }
24657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                return String.valueOf(reason);
24757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            } else {
24857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                return String.valueOf(reason);
24957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            }
25057286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        } else {
25157286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            final int index = -reason - 1;
25257286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            if (index >= REASON_NAMES.length) {
25357286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                return String.valueOf(reason);
25457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            } else {
25557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                return REASON_NAMES[index];
25657286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            }
25757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        }
25857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    }
25957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert
260918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    public boolean isInitialization() {
261918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
262918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    }
263918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana
264dc47556cb37b6f25faceb5eb97cef60d384b55fbFred Quintana    public boolean isExpedited() {
2656428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams        return expedited;
266dc47556cb37b6f25faceb5eb97cef60d384b55fbFred Quintana    }
267dc47556cb37b6f25faceb5eb97cef60d384b55fbFred Quintana
268918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    public boolean ignoreBackoff() {
269918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false);
270918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    }
271918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana
27256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public boolean isNotAllowedOnMetered() {
27356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
27456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
27556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
27692a1c09aa467f03dad78472098d40992303937fbMatthew Williams    public boolean isManual() {
27792a1c09aa467f03dad78472098d40992303937fbMatthew Williams        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
27892a1c09aa467f03dad78472098d40992303937fbMatthew Williams    }
27992a1c09aa467f03dad78472098d40992303937fbMatthew Williams
28092a1c09aa467f03dad78472098d40992303937fbMatthew Williams    public boolean isIgnoreSettings() {
28192a1c09aa467f03dad78472098d40992303937fbMatthew Williams        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
28292a1c09aa467f03dad78472098d40992303937fbMatthew Williams    }
28392a1c09aa467f03dad78472098d40992303937fbMatthew Williams
284fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** Changed in V3. */
28556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static String toKey(SyncStorageEngine.EndPoint info, Bundle extras) {
286307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        StringBuilder sb = new StringBuilder();
28756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (info.target_provider) {
28856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            sb.append("provider: ").append(info.provider);
28956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            sb.append(" account {name=" + info.account.name
29056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    + ", user="
29156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    + info.userId
29256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    + ", type="
29356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    + info.account.type
294fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    + "}");
29556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else if (info.target_service) {
296fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            sb.append("service {package=" )
29756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(info.service.getPackageName())
298fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                .append(" user=")
29956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(info.userId)
300fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                .append(", class=")
30156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(info.service.getClassName())
302fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                .append("}");
30356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else {
30456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            Log.v(TAG, "Converting SyncOperaton to key, invalid target: " + info.toString());
30556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return "";
306fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        }
307307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        sb.append(" extras: ");
308918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        extrasToStringBuilder(extras, sb);
309307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        return sb.toString();
310307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
311307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
31256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    private static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
313307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        sb.append("[");
314307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        for (String key : bundle.keySet()) {
315307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            sb.append(key).append("=").append(bundle.get(key)).append(" ");
316307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
317307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        sb.append("]");
318307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
319307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
32056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public String wakeLockName() {
321d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn        if (wakeLockName != null) {
322d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn            return wakeLockName;
323d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn        }
32456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (target.target_provider) {
325d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn            return (wakeLockName = target.provider
32656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    + "/" + target.account.type
327d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn                    + "/" + target.account.name);
32856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else if (target.target_service) {
329d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn            return (wakeLockName = target.service.getPackageName()
330d45665bf0b26fddf5716a0fd43036848d9301960Dianne Hackborn                    + "/" + target.service.getClassName());
33156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else {
33256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            Log.wtf(TAG, "Invalid target getting wakelock name for operation - " + key);
33356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return null;
33456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
33556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
33656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
337fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
338fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * Update the effective run time of this Operation based on latestRunTime (specified at
339fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * creation time of sync), delayUntil (specified by SyncAdapter), or backoff (specified by
340fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * SyncManager on soft failures).
341fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
342918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    public void updateEffectiveRunTime() {
343fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        // Regardless of whether we're in backoff or honouring a delayUntil, we still incorporate
344fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        // the flex time provided by the developer.
345fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        effectiveRunTime = ignoreBackoff() ?
346fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                latestRunTime :
347fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    Math.max(Math.max(latestRunTime, delayUntil), backoff);
348918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    }
349918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana
350fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
3517986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams     * SyncOperations are sorted based on their earliest effective run time.
3527986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams     * This comparator is used to sort the SyncOps at a given time when
3537986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams     * deciding which to run, so earliest run time is the best criteria.
354fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
355fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    @Override
356307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public int compareTo(Object o) {
357fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        SyncOperation other = (SyncOperation) o;
358918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        if (expedited != other.expedited) {
359918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana            return expedited ? -1 : 1;
360918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        }
3617986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams        long thisIntervalStart = Math.max(effectiveRunTime - flexTime, 0);
3627986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams        long otherIntervalStart = Math.max(
3637986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams            other.effectiveRunTime - other.flexTime, 0);
3647986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams        if (thisIntervalStart < otherIntervalStart) {
365fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            return -1;
3667986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams        } else if (otherIntervalStart < thisIntervalStart) {
3677986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams            return 1;
3687986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams        } else {
3697986fe490d86e92240ad1a2d8d20e01c8bb4b48cMatthew Williams            return 0;
370fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        }
371307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
37256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
37356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    // TODO: Test this to make sure that casting to object doesn't lose the type info for EventLog.
37456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public Object[] toEventLog(int event) {
37556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        Object[] logArray = new Object[4];
37656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        logArray[1] = event;
37756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        logArray[2] = syncSource;
37856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (target.target_provider) {
37956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            logArray[0] = target.provider;
38056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            logArray[3] = target.account.name.hashCode();
38156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else if (target.target_service) {
38256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            logArray[0] = target.service.getPackageName();
38356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            logArray[3] = target.service.hashCode();
38456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else {
38556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            Log.wtf(TAG, "sync op with invalid target: " + key);
38656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
38756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        return logArray;
38856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
389307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana}
390