SyncStorageEngine.java revision c5d1c6db61f208b206b260f897bb5bbc64be4d97
1231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn/*
2231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Copyright (C) 2009 The Android Open Source Project
3231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn *
4231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * you may not use this file except in compliance with the License.
6231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * You may obtain a copy of the License at
7231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn *
8231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn *
10231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * See the License for the specific language governing permissions and
14231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * limitations under the License.
15231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn */
16231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.content;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport com.android.internal.os.AtomicFile;
20231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport com.android.internal.util.ArrayUtils;
21d4a4729c0cac582a2dcec7c8cfb316b81885a0f0Tom Taylorimport com.android.common.FastXmlSerializer;
22231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
23231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport org.xmlpull.v1.XmlPullParser;
24231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
25231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport org.xmlpull.v1.XmlSerializer;
26231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
27d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintanaimport android.accounts.Account;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
30231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.database.sqlite.SQLiteException;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder;
32231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Bundle;
33231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Environment;
34231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Handler;
35231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Message;
36231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel;
37231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteCallbackList;
38231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteException;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
40231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.SparseArray;
41231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.Xml;
42307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanaimport android.util.Pair;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
44231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.File;
45231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileInputStream;
46231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileOutputStream;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
48231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Calendar;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
50231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Iterator;
51231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.TimeZone;
52c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintanaimport java.util.List;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
55231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Singleton that tracks the sync data and overall sync
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * history on the device.
57360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache *
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
60231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornpublic class SyncStorageEngine extends Handler {
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SyncManager";
62231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final boolean DEBUG = false;
63231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final boolean DEBUG_FILE = false;
64360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
65c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private static final long DEFAULT_POLL_FREQUENCY_SECONDS = 60 * 60 * 24; // One day
66c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
67231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // @VisibleForTesting
68231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
70231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync start event. */
71231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_START = 0;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
73231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync stop event. */
74231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_STOP = 1;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
76231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
77231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync event types. */
78231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] EVENTS = { "START", "STOP" };
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
80231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a server-initiated sync. */
81231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_SERVER = 0;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
83231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a local-initiated sync. */
84231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_LOCAL = 1;
85231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
86231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Enum value for a poll-based sync (e.g., upon connection to
87231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * network)
88231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
89231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_POLL = 2;
90231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
91231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a user-initiated sync. */
92231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_USER = 3;
93231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
94c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /** Enum value for a periodic sync. */
95c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public static final int SOURCE_PERIODIC = 4;
96c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
97307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public static final long NOT_IN_BACKOFF_MODE = -1;
98307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
99ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    private static final Intent SYNC_CONNECTION_SETTING_CHANGED_INTENT =
100ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
101ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
103231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync source types. */
104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] SOURCES = { "SERVER",
105231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "LOCAL",
106231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "POLL",
107c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                             "USER",
108c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                             "PERIODIC" };
109231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // The MESG column will contain one of these or one of the Error types.
111231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_SUCCESS = "success";
112231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_CANCELED = "canceled";
113231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
114a33e3f79259b56b03c7912af35944f34ad190e3cDianne Hackborn    public static final int MAX_HISTORY = 100;
115360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATUS = 1;
117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATUS_DELAY = 1000*60*10; // 10 minutes
118360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATISTICS = 2;
120231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATISTICS_DELAY = 1000*60*30; // 1/2 hour
1218294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato
1228294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato    private static final boolean SYNC_ENABLED_DEFAULT = false;
123360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class PendingOperation {
1257a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int syncSource;
127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String authority;
128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final Bundle extras;        // note: read-only.
129307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        final boolean expedited;
130360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int authorityId;
132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        byte[] flatExtras;
133360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1347a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        PendingOperation(Account account, int source,
135307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                String authority, Bundle extras, boolean expedited) {
136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = source;
138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = authority;
139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = extras != null ? new Bundle(extras) : extras;
140307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            this.expedited = expedited;
141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authorityId = -1;
142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
144231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        PendingOperation(PendingOperation other) {
145231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = other.account;
146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = other.syncSource;
147231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = other.authority;
148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = other.extras;
149231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authorityId = other.authorityId;
150307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            this.expedited = other.expedited;
151231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
152231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
153360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
154231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static class AccountInfo {
1557a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
156231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final HashMap<String, AuthorityInfo> authorities =
157231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                new HashMap<String, AuthorityInfo>();
158360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1597a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        AccountInfo(Account account) {
160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
162231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
163360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
164231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class AuthorityInfo {
1657a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
166231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String authority;
167231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int ident;
168231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean enabled;
1695e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        int syncable;
170307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        long backoffTime;
171307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        long backoffDelay;
172307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        long delayUntil;
173c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        final ArrayList<Pair<Bundle, Long>> periodicSyncs;
174ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
1757a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        AuthorityInfo(Account account, String authority, int ident) {
176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = authority;
178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.ident = ident;
1798294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            enabled = SYNC_ENABLED_DEFAULT;
1804a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana            syncable = -1; // default to "unknown"
181307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            backoffTime = -1; // if < 0 then we aren't in backoff mode
182307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            backoffDelay = -1; // if < 0 then we aren't in backoff mode
183c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            periodicSyncs = new ArrayList<Pair<Bundle, Long>>();
184c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            periodicSyncs.add(Pair.create(new Bundle(), DEFAULT_POLL_FREQUENCY_SECONDS));
185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
187360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
188231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class SyncHistoryItem {
189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int authorityId;
190231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int historyId;
191231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long eventTime;
192231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long elapsedTime;
193231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int source;
194231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int event;
195231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long upstreamActivity;
196231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long downstreamActivity;
197231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String mesg;
198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
199360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class DayStats {
201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public final int day;
202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int successCount;
203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long successTime;
204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int failureCount;
205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long failureTime;
206360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
207231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public DayStats(int day) {
208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.day = day;
209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
211360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
212231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // Primary list of all syncable authorities.  Also our global lock.
213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<AuthorityInfo> mAuthorities =
214231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<AuthorityInfo>();
215360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2167a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private final HashMap<Account, AccountInfo> mAccounts =
2177a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        new HashMap<Account, AccountInfo>();
218231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
219231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<PendingOperation> mPendingOperations =
220231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<PendingOperation>();
221360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
222231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private ActiveSyncInfo mActiveSync;
223360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
224231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<SyncStatusInfo> mSyncStatus =
225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<SyncStatusInfo>();
226360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
227231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<SyncHistoryItem> mSyncHistory =
228231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<SyncHistoryItem>();
229360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
230231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final RemoteCallbackList<ISyncStatusObserver> mChangeListeners
231231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            = new RemoteCallbackList<ISyncStatusObserver>();
232360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
233231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // We keep 4 weeks of stats.
234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final DayStats[] mDayStats = new DayStats[7*4];
235231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Calendar mCal;
236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYear;
237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYearInDays;
238360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
239231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Context mContext;
240c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
241231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static volatile SyncStorageEngine sSyncStorageEngine = null;
242360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
243231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
244231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the core engine state: all accounts and the
245231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * settings for them.  It must never be lost, and should be changed
246231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * infrequently, so it is stored as an XML file.
247231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
248231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mAccountInfoFile;
249360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
250231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
251231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the current sync status.  We would like to retain
252231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * it across boots, but its loss is not the end of the world, so we store
253231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * this information as binary data.
254231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
255231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatusFile;
256360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
257231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
258231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains sync statistics.  This is purely debugging information
259231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so is written infrequently and can be thrown away at any time.
260231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
261231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatisticsFile;
262360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
263231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
264231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the pending sync operations.  It is a binary file,
265231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * which must be updated every time an operation is added or removed,
266231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so we have special handling of it.
267231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
268231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mPendingFile;
269231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int PENDING_FINISH_TO_WRITE = 4;
270231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNumPendingFinished = 0;
271360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
272231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNextHistoryId = 0;
273ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    private boolean mMasterSyncAutomatically = true;
274360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
275c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private SyncStorageEngine(Context context, File dataDir) {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sSyncStorageEngine = this;
278360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
280360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
281231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File systemDir = new File(dataDir, "system");
282231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File syncDir = new File(systemDir, "sync");
283c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        syncDir.mkdirs();
284231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
285231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
286231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mPendingFile = new AtomicFile(new File(syncDir, "pending.bin"));
287231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
288360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
289231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readAccountInfoLocked();
290231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatusLocked();
291231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readPendingOperationsLocked();
292231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatisticsLocked();
293231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readLegacyAccountInfoLocked();
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine newTestInstance(Context context) {
297c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return new SyncStorageEngine(context, context.getFilesDir());
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void init(Context context) {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine != null) {
302307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            return;
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
304c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        // This call will return the correct directory whether Encrypted File Systems is
305c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        // enabled or not.
306c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        File dataDir = Environment.getSecureDataDirectory();
307c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        sSyncStorageEngine = new SyncStorageEngine(context, dataDir);
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine getSingleton() {
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine == null) {
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("not initialized");
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sSyncStorageEngine;
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
317231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    @Override public void handleMessage(Message msg) {
318231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (msg.what == MSG_WRITE_STATUS) {
319231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            synchronized (mAccounts) {
320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
321231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } else if (msg.what == MSG_WRITE_STATISTICS) {
323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            synchronized (mAccounts) {
324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
328360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
329231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
331231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.register(callback, mask);
332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
334360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void removeStatusChangeListener(ISyncStatusObserver callback) {
336231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
337231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.unregister(callback);
338231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
339231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
340360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
341231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void reportChange(int which) {
342231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        ArrayList<ISyncStatusObserver> reports = null;
343231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
344231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mChangeListeners.beginBroadcast();
345231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
346231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
347231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Integer mask = (Integer)mChangeListeners.getBroadcastCookie(i);
348231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if ((which & mask.intValue()) == 0) {
349231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
350231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
351231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (reports == null) {
352231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports = new ArrayList<ISyncStatusObserver>(i);
353231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
354231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                reports.add(mChangeListeners.getBroadcastItem(i));
355231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
356b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            mChangeListeners.finishBroadcast();
357231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
358360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG) Log.v(TAG, "reportChange " + which + " to: " + reports);
360360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (reports != null) {
362231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = reports.size();
363231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports.get(i).onStatusChanged(which);
367231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (RemoteException e) {
368231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // The remote callback list will take care of this for us.
369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
370231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
37370c874ba20b586712a7550b6c5efeb6dc0fdf9faAmith Yamasani
374ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getSyncAutomatically(Account account, String providerName) {
375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
376231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (account != null) {
377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(account, providerName,
378ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        "getSyncAutomatically");
379ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return authority != null && authority.enabled;
380231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
381ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mAuthorities.size();
383231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
384231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
385360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                AuthorityInfo authority = mAuthorities.valueAt(i);
386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority.authority.equals(providerName)
387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        && authority.enabled) {
388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
391231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
395ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setSyncAutomatically(Account account, String providerName, boolean sync) {
3968294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        boolean wasEnabled;
397231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
3988294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
3998294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            wasEnabled = authority.enabled;
4008294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            authority.enabled = sync;
401231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4038294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato
4048294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        if (!wasEnabled && sync) {
405307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            ContentResolver.requestSync(account, providerName, new Bundle());
4068294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        }
407ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4105e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    public int getIsSyncable(Account account, String providerName) {
4115e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        synchronized (mAuthorities) {
4125e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            if (account != null) {
4135e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                AuthorityInfo authority = getAuthorityLocked(account, providerName,
4145e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                        "getIsSyncable");
4155e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                if (authority == null) {
4165e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    return -1;
4175e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
4185e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                return authority.syncable;
4195e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
4205e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
4215e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            int i = mAuthorities.size();
4225e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            while (i > 0) {
4235e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                i--;
424360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                AuthorityInfo authority = mAuthorities.valueAt(i);
4255e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                if (authority.authority.equals(providerName)) {
4265e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    return authority.syncable;
4275e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
4285e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
4295e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            return -1;
4305e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
4315e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
4325e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
4335e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    public void setIsSyncable(Account account, String providerName, int syncable) {
4345e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        int oldState;
435b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana        if (syncable > 1) {
436b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana            syncable = 1;
437b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana        } else if (syncable < -1) {
438b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana            syncable = -1;
439b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana        }
440b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana        Log.d(TAG, "setIsSyncable: " + account + ", provider " + providerName + " -> " + syncable);
4415e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        synchronized (mAuthorities) {
4425e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
4435e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            oldState = authority.syncable;
4445e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            authority.syncable = syncable;
4455e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            writeAccountInfoLocked();
4465e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
4475e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
4485e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        if (oldState <= 0 && syncable > 0) {
449307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            ContentResolver.requestSync(account, providerName, new Bundle());
4505e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
4515e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
4525e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
4535e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
454307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public Pair<Long, Long> getBackoff(Account account, String providerName) {
455307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
456307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            AuthorityInfo authority = getAuthorityLocked(account, providerName, "getBackoff");
457307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            if (authority == null || authority.backoffTime < 0) {
458307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                return null;
459307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
460307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            return Pair.create(authority.backoffTime, authority.backoffDelay);
461307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
462307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
463307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
464307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public void setBackoff(Account account, String providerName,
465307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            long nextSyncTime, long nextDelay) {
466307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
467307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            Log.v(TAG, "setBackoff: " + account + ", provider " + providerName
468307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    + " -> nextSyncTime " + nextSyncTime + ", nextDelay " + nextDelay);
469307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
470307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        boolean changed = false;
471307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
472307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            if (account == null || providerName == null) {
473307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                for (AccountInfo accountInfo : mAccounts.values()) {
474307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    if (account != null && !account.equals(accountInfo.account)) continue;
475307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
476307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                        if (providerName != null && !providerName.equals(authorityInfo.authority)) {
477307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            continue;
478307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                        }
479307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                        if (authorityInfo.backoffTime != nextSyncTime
480307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                                || authorityInfo.backoffDelay != nextDelay) {
481307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            authorityInfo.backoffTime = nextSyncTime;
482307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            authorityInfo.backoffDelay = nextDelay;
483307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            changed = true;
484307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                        }
485307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    }
486307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                }
487307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            } else {
488307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                AuthorityInfo authority =
489c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        getOrCreateAuthorityLocked(account, providerName, -1 /* ident */, true);
490307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                if (authority.backoffTime == nextSyncTime && authority.backoffDelay == nextDelay) {
491307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    return;
492307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                }
493307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                authority.backoffTime = nextSyncTime;
494307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                authority.backoffDelay = nextDelay;
495307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                changed = true;
496307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
497307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
498307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
499307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        if (changed) {
500307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
501307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
502307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
503307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
504307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public void setDelayUntilTime(Account account, String providerName, long delayUntil) {
505307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
506307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            Log.v(TAG, "setDelayUntil: " + account + ", provider " + providerName
507307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    + " -> delayUntil " + delayUntil);
508307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
509307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
510c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            AuthorityInfo authority = getOrCreateAuthorityLocked(
511c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    account, providerName, -1 /* ident */, true);
512307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            if (authority.delayUntil == delayUntil) {
513307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                return;
514307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
515307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            authority.delayUntil = delayUntil;
516307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
517307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
518307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
519307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
520307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
521307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public long getDelayUntilTime(Account account, String providerName) {
522307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
523307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            AuthorityInfo authority = getAuthorityLocked(account, providerName, "getDelayUntil");
524307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            if (authority == null) {
525307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                return 0;
526307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
527307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            return authority.delayUntil;
528307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
529307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
530307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
531c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private void updateOrRemovePeriodicSync(Account account, String providerName, Bundle extras,
532c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            long period, boolean add) {
533c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (period <= 0) {
534c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            period = 0;
535c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
536c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (extras == null) {
537c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            extras = new Bundle();
538c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
539c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
540c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.v(TAG, "addOrRemovePeriodicSync: " + account + ", provider " + providerName
541c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    + " -> period " + period + ", extras " + extras);
542c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
543c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
544c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
545c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (add) {
546c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                boolean alreadyPresent = false;
547c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                for (int i = 0, N = authority.periodicSyncs.size(); i < N; i++) {
548c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    Pair<Bundle, Long> syncInfo = authority.periodicSyncs.get(i);
549c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    final Bundle existingExtras = syncInfo.first;
550c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    if (equals(existingExtras, extras)) {
551c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        if (syncInfo.second == period) {
552c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            return;
553c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        }
554c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        authority.periodicSyncs.set(i, Pair.create(extras, period));
555c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        alreadyPresent = true;
556c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        break;
557c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    }
558c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
559c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                if (!alreadyPresent) {
560c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    authority.periodicSyncs.add(Pair.create(extras, period));
561c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
562c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    status.setPeriodicSyncTime(authority.periodicSyncs.size() - 1, 0);
563c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
564c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else {
565c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                SyncStatusInfo status = mSyncStatus.get(authority.ident);
566c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                boolean changed = false;
567c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                Iterator<Pair<Bundle, Long>> iterator = authority.periodicSyncs.iterator();
568c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                int i = 0;
569c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                while (iterator.hasNext()) {
570c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    Pair<Bundle, Long> syncInfo = iterator.next();
571c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    if (equals(syncInfo.first, extras)) {
572c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        iterator.remove();
573c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        changed = true;
574c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        if (status != null) {
575c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            status.removePeriodicSyncTime(i);
576c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        }
577c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    } else {
578c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        i++;
579c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    }
580c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
581c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                if (!changed) {
582c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    return;
583c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
584c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
585c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            writeAccountInfoLocked();
586c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            writeStatusLocked();
587c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
588c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
589c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
590c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
591c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
592c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public void addPeriodicSync(Account account, String providerName, Bundle extras,
593c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            long pollFrequency) {
594c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        updateOrRemovePeriodicSync(account, providerName, extras, pollFrequency, true /* add */);
595c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
596c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
597c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public void removePeriodicSync(Account account, String providerName, Bundle extras) {
598c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        updateOrRemovePeriodicSync(account, providerName, extras, 0 /* period, ignored */,
599c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                false /* remove */);
600c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
601c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
602c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public List<PeriodicSync> getPeriodicSyncs(Account account, String providerName) {
603c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        ArrayList<PeriodicSync> syncs = new ArrayList<PeriodicSync>();
604c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
605c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            AuthorityInfo authority = getAuthorityLocked(account, providerName, "getPeriodicSyncs");
606c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (authority != null) {
607c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                for (Pair<Bundle, Long> item : authority.periodicSyncs) {
608c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    syncs.add(new PeriodicSync(account, providerName, item.first, item.second));
609c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
610c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
611c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
612c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return syncs;
613c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
614c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
615ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setMasterSyncAutomatically(boolean flag) {
6168294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        boolean old;
617231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
6188294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            old = mMasterSyncAutomatically;
619ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            mMasterSyncAutomatically = flag;
620231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6228294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        if (!old && flag) {
623307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            ContentResolver.requestSync(null, null, new Bundle());
6248294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        }
625ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
626ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        mContext.sendBroadcast(SYNC_CONNECTION_SETTING_CHANGED_INTENT);
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getMasterSyncAutomatically() {
630231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
631ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            return mMasterSyncAutomatically;
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
634360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
6357a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public AuthorityInfo getAuthority(Account account, String authority) {
636231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
637231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return getAuthorityLocked(account, authority, null);
638231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
640360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
641231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public AuthorityInfo getAuthority(int authorityId) {
642231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
643231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mAuthorities.get(authorityId);
644231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
645231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
646360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
648231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Returns true if there is currently a sync operation for the given
649231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * account or authority in the pending list, or actively being processed.
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6517a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public boolean isSyncActive(Account account, String authority) {
652231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
653231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mPendingOperations.size();
654231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
655231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
656231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // TODO(fredq): this probably shouldn't be considering
657231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // pending operations.
658231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                PendingOperation op = mPendingOperations.get(i);
659231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (op.account.equals(account) && op.authority.equals(authority)) {
660231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
661231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
662231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
663360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
664231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mActiveSync != null) {
665231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = getAuthority(mActiveSync.authorityId);
666231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo != null && ainfo.account.equals(account)
667231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        && ainfo.authority.equals(authority)) {
668231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
669231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
670231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
672360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
673231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
674231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
675360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
676231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public PendingOperation insertIntoPending(PendingOperation op) {
677231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
678231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertIntoPending: account=" + op.account
679231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
680231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
681231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
682360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
683231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getOrCreateAuthorityLocked(op.account,
684231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.authority,
685231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    -1 /* desired identifier */,
686231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    true /* write accounts to storage */);
687231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
688231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return null;
689231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
690360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
691231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op = new PendingOperation(op);
692231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op.authorityId = authority.ident;
693231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.add(op);
694231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            appendPendingOperationLocked(op);
695360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
696231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
697231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.pending = true;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
699360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
700ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
701231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return op;
702231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
704231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean deleteFromPending(PendingOperation op) {
705231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean res = false;
706231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
707231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "deleteFromPending: account=" + op.account
708231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
709231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
710231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
711231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mPendingOperations.remove(op)) {
712231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mPendingOperations.size() == 0
713231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || mNumPendingFinished >= PENDING_FINISH_TO_WRITE) {
714231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writePendingOperationsLocked();
715231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished = 0;
716231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
717231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished++;
718231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
719360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(op.account, op.authority,
721231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "deleteFromPending");
722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
723231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.v(TAG, "removing - " + authority);
724231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    final int N = mPendingOperations.size();
725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean morePending = false;
726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (int i=0; i<N; i++) {
727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        PendingOperation cur = mPendingOperations.get(i);
728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (cur.account.equals(op.account)
729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                && cur.authority.equals(op.authority)) {
730231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            morePending = true;
731231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
732231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
733231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
734360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
735231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!morePending) {
736231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (DEBUG) Log.v(TAG, "no more pending!");
737231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
738231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
739231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
740231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
741360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
742231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                res = true;
743231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
744231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
745360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
746ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
747231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return res;
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
750231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int clearPending() {
751231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int num;
752231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
753231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "clearPending");
754231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            num = mPendingOperations.size();
755231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.clear();
756231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
757231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
758360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                mSyncStatus.valueAt(i).pending = false;
759231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
760231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationsLocked();
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
762ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
763231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return num;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
767231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return a copy of the current array of pending operations.  The
768231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * PendingOperation objects are the real objects stored inside, so that
769231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * they can be used with deleteFromPending().
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
771231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<PendingOperation> getPendingOperations() {
772231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
773231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return new ArrayList<PendingOperation>(mPendingOperations);
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
776360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
778231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the number of currently pending operations.
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
780231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int getPendingOperationCount() {
781231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
782231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mPendingOperations.size();
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
785360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
787231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the set of account has changed, given the new array of
788231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active accounts.
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7907a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public void doDatabaseCleanup(Account[] accounts) {
791231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
792231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.w(TAG, "Updating for new accounts...");
793231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SparseArray<AuthorityInfo> removing = new SparseArray<AuthorityInfo>();
794231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Iterator<AccountInfo> accIt = mAccounts.values().iterator();
795231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (accIt.hasNext()) {
796231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AccountInfo acc = accIt.next();
797231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!ArrayUtils.contains(accounts, acc.account)) {
798231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // This account no longer exists...
799231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.w(TAG, "Account removed: " + acc.account);
800231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (AuthorityInfo auth : acc.authorities.values()) {
801231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        removing.put(auth.ident, auth);
802231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
803231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    accIt.remove();
804231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
805231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
806360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
807231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Clean out all data structures.
808231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = removing.size();
809231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (i > 0) {
810231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                while (i > 0) {
811231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    i--;
812231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int ident = removing.keyAt(i);
813231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mAuthorities.remove(ident);
814231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int j = mSyncStatus.size();
815231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
816231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
817231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncStatus.keyAt(j) == ident) {
818231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncStatus.remove(mSyncStatus.keyAt(j));
819231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
820231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
821231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    j = mSyncHistory.size();
822231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
823231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
824231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncHistory.get(j).authorityId == ident) {
825231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncHistory.remove(j);
826231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
827231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
828231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
829231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
830231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
831231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationsLocked();
832231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
833231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
837231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
838231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the currently active sync is changing (there can only be
839231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * one at a time).  Either supply a valid ActiveSyncContext with information
840231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * about the sync, or null to stop the currently active sync.
841231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
842231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void setActiveSync(SyncManager.ActiveSyncContext activeSyncContext) {
843231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
844231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (activeSyncContext != null) {
845231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: account="
846231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + activeSyncContext.mSyncOperation.account
847231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " auth=" + activeSyncContext.mSyncOperation.authority
848231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " src=" + activeSyncContext.mSyncOperation.syncSource
849231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " extras=" + activeSyncContext.mSyncOperation.extras);
850231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mActiveSync != null) {
851231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "setActiveSync called with existing active sync!");
852231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
853231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(
854231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.account,
855231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.authority,
856231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "setActiveSync");
857231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority == null) {
858231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return;
859231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
860231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = new ActiveSyncInfo(authority.ident,
861231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        authority.account, authority.authority,
862231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mStartTime);
863231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else {
864231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: null");
865231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = null;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
868360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
869ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
872231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
873231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * To allow others to send active change reports, to poke clients.
874231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
875231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void reportActiveChange() {
876ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
877231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
878360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
879231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
880231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Note that sync has started for the given account and authority.
881231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
8827a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public long insertStartSyncEvent(Account accountName, String authorityName,
883231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long now, int source) {
884231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long id;
885231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
886231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertStartSyncEvent: account=" + accountName
887231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + authorityName + " source=" + source);
888231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getAuthorityLocked(accountName, authorityName,
889231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    "insertStartSyncEvent");
890231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
891231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return -1;
892231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
893231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = new SyncHistoryItem();
894231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.authorityId = authority.ident;
895231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.historyId = mNextHistoryId++;
896231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mNextHistoryId < 0) mNextHistoryId = 0;
897231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.eventTime = now;
898231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.source = source;
899231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_START;
900231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncHistory.add(0, item);
901231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (mSyncHistory.size() > MAX_HISTORY) {
902231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mSyncHistory.remove(mSyncHistory.size()-1);
903231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
904231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            id = item.historyId;
905231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "returning historyId " + id);
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
907360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
908ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
909231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return id;
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
912c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public static boolean equals(Bundle b1, Bundle b2) {
913c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (b1.size() != b2.size()) {
914c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return false;
915c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
916c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (b1.isEmpty()) {
917c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return true;
918c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
919c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        for (String key : b1.keySet()) {
920c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (!b2.containsKey(key)) {
921c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                return false;
922c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
923c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (!b1.get(key).equals(b2.get(key))) {
924c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                return false;
925c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
926c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
927c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return true;
928c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
929c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
930c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public void stopSyncEvent(long historyId, Bundle extras, long elapsedTime, String resultMessage,
931231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long downstreamActivity, long upstreamActivity) {
932231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
933231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "stopSyncEvent: historyId=" + historyId);
934231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = null;
935231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncHistory.size();
936231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
937231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
938231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = mSyncHistory.get(i);
939231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (item.historyId == historyId) {
940231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
941231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
942231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = null;
943231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
944360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
945231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (item == null) {
946231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, "stopSyncEvent: no history for id " + historyId);
947231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
948231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
949360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
950231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.elapsedTime = elapsedTime;
951231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_STOP;
952231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.mesg = resultMessage;
953231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.downstreamActivity = downstreamActivity;
954231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.upstreamActivity = upstreamActivity;
955360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
956231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(item.authorityId);
957360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
958231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.numSyncs++;
959231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.totalElapsedTime += elapsedTime;
960231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            switch (item.source) {
961231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_LOCAL:
962231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceLocal++;
963231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
964231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_POLL:
965231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourcePoll++;
966231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
967231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_USER:
968231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceUser++;
969231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
970231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_SERVER:
971231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceServer++;
972231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
973c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                case SOURCE_PERIODIC:
974c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    status.numSourcePeriodic++;
975c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    AuthorityInfo authority = mAuthorities.get(item.authorityId);
976c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    for (int periodicSyncIndex = 0;
977c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            periodicSyncIndex < authority.periodicSyncs.size();
978c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            periodicSyncIndex++) {
979c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        if (equals(extras, authority.periodicSyncs.get(periodicSyncIndex).first)) {
980c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            status.setPeriodicSyncTime(periodicSyncIndex, item.eventTime);
981c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        }
982c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    }
983c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    break;
984231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
985360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
986231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatisticsNow = false;
98755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            int day = getCurrentDayLocked();
988231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mDayStats[0] == null) {
989231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
990231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (day != mDayStats[0].day) {
991231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                System.arraycopy(mDayStats, 0, mDayStats, 1, mDayStats.length-1);
992231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
993231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsNow = true;
994231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (mDayStats[0] == null) {
995231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
996231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final DayStats ds = mDayStats[0];
997360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
998231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final long lastSyncTime = (item.eventTime + elapsedTime);
999231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatusNow = false;
1000231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (MESG_SUCCESS.equals(resultMessage)) {
1001231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // - if successful, update the successful columns
1002231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastSuccessTime == 0 || status.lastFailureTime != 0) {
1003231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
1004231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1005231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessTime = lastSyncTime;
1006231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessSource = item.source;
1007231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = 0;
1008231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = -1;
1009231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = null;
1010231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.initialFailureTime = 0;
1011231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successCount++;
1012231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successTime += elapsedTime;
1013231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!MESG_CANCELED.equals(resultMessage)) {
1014231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastFailureTime == 0) {
1015231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
1016231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1017231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = lastSyncTime;
1018231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = item.source;
1019231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = resultMessage;
1020231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.initialFailureTime == 0) {
1021231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.initialFailureTime = lastSyncTime;
1022231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1023231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureCount++;
1024231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureTime += elapsedTime;
1025231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1026360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1027231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatusNow) {
1028231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
1029231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATUS)) {
1030231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATUS),
1031231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATUS_DELAY);
1032231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1033231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatisticsNow) {
1034231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
1035231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATISTICS)) {
1036231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATISTICS),
1037231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATISTICS_DELAY);
1038360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache            }
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1040360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1041ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1045231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the currently active sync information, or null if there is no
1046231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active sync.  Note that the returned object is the real, live active
1047231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync object, so be careful what you do with it.
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1049231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ActiveSyncInfo getActiveSync() {
1050231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1051231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mActiveSync;
1052231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1054360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1055231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1056231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
1057231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1058231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1059231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1060231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncStatusInfo> getSyncStatus() {
1061231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1062231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1063231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncStatusInfo> ops = new ArrayList<SyncStatusInfo>(N);
1064231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1065231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ops.add(mSyncStatus.valueAt(i));
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1067231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ops;
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1070360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1071231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1072c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * Return an array of the current authorities. Note
1073c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * that the objects inside the array are the real, live objects,
1074c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * so be careful what you do with them.
1075c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     */
1076c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public ArrayList<AuthorityInfo> getAuthorities() {
1077c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
1078c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            final int N = mAuthorities.size();
1079c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            ArrayList<AuthorityInfo> infos = new ArrayList<AuthorityInfo>(N);
1080c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            for (int i=0; i<N; i++) {
1081c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                infos.add(mAuthorities.valueAt(i));
1082c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1083c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return infos;
1084c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1085c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1086c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1087c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /**
1088b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     * Returns the status that matches the authority and account.
1089b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     *
1090b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     * @param account the account we want to check
1091231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authority the authority whose row should be selected
1092c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @return the SyncStatusInfo for the authority
1093231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1094b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache    public SyncStatusInfo getStatusByAccountAndAuthority(Account account, String authority) {
1095b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache        if (account == null || authority == null) {
1096b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache          throw new IllegalArgumentException();
1097b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache        }
1098231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1099231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1100231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1101360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                SyncStatusInfo cur = mSyncStatus.valueAt(i);
1102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
1103b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
1104b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                if (ainfo != null && ainfo.authority.equals(authority) &&
1105b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                    account.equals(ainfo.account)) {
1106b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                  return cur;
1107231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1108231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1109b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache            return null;
1110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1112360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1113231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return true if the pending status is true of any matching authorities.
1115231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1116ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean isSyncPending(Account account, String authority) {
1117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1120360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                SyncStatusInfo cur = mSyncStatus.valueAt(i);
1121231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
1122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo == null) {
1123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
1124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (account != null && !ainfo.account.equals(account)) {
1126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
1127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo.authority.equals(authority) && cur.pending) {
1129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
1138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncHistoryItem> getSyncHistory() {
1142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncHistory.size();
1144231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncHistoryItem> items = new ArrayList<SyncHistoryItem>(N);
1145231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                items.add(mSyncHistory.get(i));
1147231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return items;
1149231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1150231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1151360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1152231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1153231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current per-day statistics.  Note
1154231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1155231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1156231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1157231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public DayStats[] getDayStatistics() {
1158231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1159231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            DayStats[] ds = new DayStats[mDayStats.length];
1160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            System.arraycopy(mDayStats, 0, ds, 0, ds.length);
1161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ds;
1162231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1163231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1164360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1165231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If sync is failing for any of the provider/accounts then determine the time at which it
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * started failing and return the earliest time over all the provider/accounts. If none are
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * failing then return 0.
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getInitialSyncFailureTime() {
1171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1172ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (!mMasterSyncAutomatically) {
1173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return 0;
1174231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1175360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long oldest = 0;
1177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncStatus.size();
1178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
1179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
1180231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo stats = mSyncStatus.valueAt(i);
1181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(stats.authorityId);
1182231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null && authority.enabled) {
1183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (oldest == 0 || stats.initialFailureTime < oldest) {
1184231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        oldest = stats.initialFailureTime;
1185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1188360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return oldest;
1190231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1191231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1192360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
119355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private int getCurrentDayLocked() {
1194231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal.setTimeInMillis(System.currentTimeMillis());
1195231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
1196231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (mYear != mCal.get(Calendar.YEAR)) {
1197231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYear = mCal.get(Calendar.YEAR);
1198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.clear();
1199231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.set(Calendar.YEAR, mYear);
1200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYearInDays = (int)(mCal.getTimeInMillis()/86400000);
1201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return dayOfYear + mYearInDays;
1203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1204360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1206231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Retrieve an authority, returning null if one does not exist.
1207360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache     *
1208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param accountName The name of the account for the authority.
1209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authorityName The name of the authority itself.
1210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param tag If non-null, this will be used in a log message if the
1211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * requested authority does not exist.
1212231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
12137a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private AuthorityInfo getAuthorityLocked(Account accountName, String authorityName,
1214231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tag) {
1215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
1216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
1217231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
1218b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
1219b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                    Log.v(TAG, tag + ": unknown account " + accountName);
1220b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                }
1221231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1222231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
1223231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1224231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
1225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
1226231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
1227b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
1228b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                    Log.v(TAG, tag + ": unknown authority " + authorityName);
1229b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                }
1230231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1231231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
1232231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1233360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
1235231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1236360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
12377a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private AuthorityInfo getOrCreateAuthorityLocked(Account accountName,
1238231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String authorityName, int ident, boolean doWrite) {
1239231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
1240231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
1241231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account = new AccountInfo(accountName);
1242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccounts.put(accountName, account);
1243231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1244231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
1245231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
1246231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (ident < 0) {
1247231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // Look for a new identifier for this authority.
1248231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                final int N = mAuthorities.size();
1249231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ident = 0;
1250231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                for (int i=0; i<N; i++) {
1251231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.valueAt(i).ident > ident) {
1252231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        break;
1253231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1254231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ident++;
1255231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1256231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1257bd0a81ff1c0e92e80e05e2f12bb1805c7d081e94Dianne Hackborn            if (DEBUG) Log.v(TAG, "created a new AuthorityInfo for " + accountName
1258b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                    + ", provider " + authorityName);
1259231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            authority = new AuthorityInfo(accountName, authorityName, ident);
1260231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account.authorities.put(authorityName, authority);
1261231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAuthorities.put(ident, authority);
1262231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (doWrite) {
1263231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
1264231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1265231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1266360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1267231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
1268231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1269360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1270c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public SyncStatusInfo getOrCreateSyncStatus(AuthorityInfo authority) {
1271c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
1272c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return getOrCreateSyncStatusLocked(authority.ident);
1273c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1274c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1275c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1276231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private SyncStatusInfo getOrCreateSyncStatusLocked(int authorityId) {
1277231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SyncStatusInfo status = mSyncStatus.get(authorityId);
1278231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (status == null) {
1279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status = new SyncStatusInfo(authorityId);
1280231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncStatus.put(authorityId, status);
1281231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1282231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return status;
1283231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1284360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
128555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    public void writeAllState() {
128655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        synchronized (mAuthorities) {
128755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Account info is always written so no need to do it here.
1288360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
128955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            if (mNumPendingFinished > 0) {
129055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                // Only write these if they are out of date.
129155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                writePendingOperationsLocked();
129255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
1293360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
129455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Just always write these...  they are likely out of date.
129555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatusLocked();
129655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatisticsLocked();
129755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
129855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
1299360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1300231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1301c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * public for testing
1302c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     */
1303c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public void clearAndReadState() {
1304c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
1305c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mAuthorities.clear();
1306c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mAccounts.clear();
1307c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mPendingOperations.clear();
1308c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mSyncStatus.clear();
1309c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mSyncHistory.clear();
1310c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1311c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readAccountInfoLocked();
1312c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readStatusLocked();
1313c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readPendingOperationsLocked();
1314c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readStatisticsLocked();
1315c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readLegacyAccountInfoLocked();
1316c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1317c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1318c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1319c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /**
1320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all account information back in to the initial engine state.
1321231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readAccountInfoLocked() {
1323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileInputStream fis = null;
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1325231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fis = mAccountInfoFile.openRead();
1326231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading " + mAccountInfoFile.getBaseFile());
1327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlPullParser parser = Xml.newPullParser();
1328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parser.setInput(fis, null);
1329231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int eventType = parser.getEventType();
1330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (eventType != XmlPullParser.START_TAG) {
1331231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tagName = parser.getName();
1334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if ("accounts".equals(tagName)) {
1335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String listen = parser.getAttributeValue(
1336231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        null, "listen-for-tickles");
1337ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                mMasterSyncAutomatically = listen == null
1338231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            || Boolean.parseBoolean(listen);
1339231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1340c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                AuthorityInfo authority = null;
1341c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                Pair<Bundle, Long> periodicSync = null;
1342231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                do {
1343c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    if (eventType == XmlPullParser.START_TAG) {
1344231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        tagName = parser.getName();
1345c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        if (parser.getDepth() == 2) {
1346c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            if ("authority".equals(tagName)) {
1347c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                authority = parseAuthority(parser);
1348c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                periodicSync = null;
1349231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1350c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (parser.getDepth() == 3) {
1351c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            if ("periodicSync".equals(tagName) && authority != null) {
1352c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                periodicSync = parsePeriodicSync(parser, authority);
1353c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            }
1354c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (parser.getDepth() == 4 && periodicSync != null) {
1355c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            if ("extra".equals(tagName)) {
1356c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                parseExtra(parser, periodicSync);
1357231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1358231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1360231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    eventType = parser.next();
1361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } while (eventType != XmlPullParser.END_DOCUMENT);
1362231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1363231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (XmlPullParserException e) {
1364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error reading accounts", e);
1365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis == null) Log.i(TAG, "No initial accounts");
1367231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            else Log.w(TAG, "Error reading accounts", e);
1368231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis != null) {
1370231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
1371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    fis.close();
1372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (java.io.IOException e1) {
1373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1374231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1376231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1377360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1378c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private AuthorityInfo parseAuthority(XmlPullParser parser) {
1379c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        AuthorityInfo authority = null;
1380c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        int id = -1;
1381c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
1382c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            id = Integer.parseInt(parser.getAttributeValue(
1383c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    null, "id"));
1384c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NumberFormatException e) {
1385c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing the id of the authority", e);
1386c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NullPointerException e) {
1387c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "the id of the authority is null", e);
1388c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1389c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (id >= 0) {
1390c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String accountName = parser.getAttributeValue(null, "account");
1391c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String accountType = parser.getAttributeValue(null, "type");
1392c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (accountType == null) {
1393c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                accountType = "com.google";
1394c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1395c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String authorityName = parser.getAttributeValue(null, "authority");
1396c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String enabled = parser.getAttributeValue(null, "enabled");
1397c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String syncable = parser.getAttributeValue(null, "syncable");
1398c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            authority = mAuthorities.get(id);
1399c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (DEBUG_FILE) Log.v(TAG, "Adding authority: account="
1400c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    + accountName + " auth=" + authorityName
1401c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    + " enabled=" + enabled
1402c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    + " syncable=" + syncable);
1403c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (authority == null) {
1404c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                if (DEBUG_FILE) Log.v(TAG, "Creating entry");
1405c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                authority = getOrCreateAuthorityLocked(
1406c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        new Account(accountName, accountType), authorityName, id, false);
1407c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                // clear this since we will read these later on
1408c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                authority.periodicSyncs.clear();
1409c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1410c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (authority != null) {
1411c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                authority.enabled = enabled == null || Boolean.parseBoolean(enabled);
1412c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                if ("unknown".equals(syncable)) {
1413c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    authority.syncable = -1;
1414c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                } else {
1415c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    authority.syncable =
1416c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            (syncable == null || Boolean.parseBoolean(enabled)) ? 1 : 0;
1417c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
1418c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else {
1419c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                Log.w(TAG, "Failure adding authority: account="
1420c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        + accountName + " auth=" + authorityName
1421c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        + " enabled=" + enabled
1422c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        + " syncable=" + syncable);
1423c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1424c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1425c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1426c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return authority;
1427c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1428c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1429c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private Pair<Bundle, Long> parsePeriodicSync(XmlPullParser parser, AuthorityInfo authority) {
1430c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        Bundle extras = new Bundle();
1431c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String periodValue = parser.getAttributeValue(null, "period");
1432c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        final long period;
1433c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
1434c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            period = Long.parseLong(periodValue);
1435c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NumberFormatException e) {
1436c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing the period of a periodic sync", e);
1437c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return null;
1438c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NullPointerException e) {
1439c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "the period of a periodic sync is null", e);
1440c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return null;
1441c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1442c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        final Pair<Bundle, Long> periodicSync = Pair.create(extras, period);
1443c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        authority.periodicSyncs.add(periodicSync);
1444c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return periodicSync;
1445c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1446c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1447c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private void parseExtra(XmlPullParser parser, Pair<Bundle, Long> periodicSync) {
1448c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        final Bundle extras = periodicSync.first;
1449c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String name = parser.getAttributeValue(null, "name");
1450c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String type = parser.getAttributeValue(null, "type");
1451c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String value1 = parser.getAttributeValue(null, "value1");
1452c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String value2 = parser.getAttributeValue(null, "value2");
1453c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1454c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
1455c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if ("long".equals(type)) {
1456c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putLong(name, Long.parseLong(value1));
1457c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("integer".equals(type)) {
1458c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putInt(name, Integer.parseInt(value1));
1459c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("double".equals(type)) {
1460c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putDouble(name, Double.parseDouble(value1));
1461c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("float".equals(type)) {
1462c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putFloat(name, Float.parseFloat(value1));
1463c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("boolean".equals(type)) {
1464c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putBoolean(name, Boolean.parseBoolean(value1));
1465c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("string".equals(type)) {
1466c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putString(name, value1);
1467c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("account".equals(type)) {
1468c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putParcelable(name, new Account(value1, value2));
1469c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1470c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NumberFormatException e) {
1471c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing bundle value", e);
1472c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NullPointerException e) {
1473c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing bundle value", e);
1474c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1475c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1476c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1477231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1478231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all account information to the account file.
1479231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1480231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeAccountInfoLocked() {
1481231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
1482231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1483360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1484231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1485231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mAccountInfoFile.startWrite();
1486231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlSerializer out = new FastXmlSerializer();
1487231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setOutput(fos, "utf-8");
1488231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startDocument(null, true);
1489231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1490360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1491231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startTag(null, "accounts");
1492ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (!mMasterSyncAutomatically) {
1493231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "listen-for-tickles", "false");
1494231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1495360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1496231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mAuthorities.size();
1497231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1498360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                AuthorityInfo authority = mAuthorities.valueAt(i);
1499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.startTag(null, "authority");
1500231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "id", Integer.toString(authority.ident));
1501ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                out.attribute(null, "account", authority.account.name);
1502ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                out.attribute(null, "type", authority.account.type);
1503231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "authority", authority.authority);
1504231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!authority.enabled) {
1505231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    out.attribute(null, "enabled", "false");
1506231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
15075e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                if (authority.syncable < 0) {
15085e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    out.attribute(null, "syncable", "unknown");
15095e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                } else if (authority.syncable == 0) {
15105e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    out.attribute(null, "syncable", "false");
15115e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
1512c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                for (Pair<Bundle, Long> periodicSync : authority.periodicSyncs) {
1513c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    out.startTag(null, "periodicSync");
1514c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    out.attribute(null, "period", Long.toString(periodicSync.second));
1515c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    final Bundle extras = periodicSync.first;
1516c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    for (String key : extras.keySet()) {
1517c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        out.startTag(null, "extra");
1518c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        out.attribute(null, "name", key);
1519c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        final Object value = extras.get(key);
1520c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        if (value instanceof Long) {
1521c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "long");
1522c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1523c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Integer) {
1524c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "integer");
1525c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1526c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Boolean) {
1527c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "boolean");
1528c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1529c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Float) {
1530c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "float");
1531c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1532c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Double) {
1533c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "double");
1534c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1535c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof String) {
1536c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "string");
1537c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1538c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Account) {
1539c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "account");
1540c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", ((Account)value).name);
1541c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value2", ((Account)value).type);
1542c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        }
1543c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        out.endTag(null, "extra");
1544c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    }
1545c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    out.endTag(null, "periodicSync");
1546c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
1547231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.endTag(null, "authority");
1548231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1549360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endTag(null, "accounts");
1551360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1552231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endDocument();
1553360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1554231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccountInfoFile.finishWrite(fos);
1555231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1556231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing accounts", e1);
1557231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1558231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mAccountInfoFile.failWrite(fos);
1559231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1560231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1562360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static int getIntColumn(Cursor c, String name) {
1564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getInt(c.getColumnIndex(name));
1565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1566360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1567231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static long getLongColumn(Cursor c, String name) {
1568231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getLong(c.getColumnIndex(name));
1569231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1570360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1571231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1572231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Load sync engine state from the old syncmanager database, and then
1573231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * erase it.  Note that we don't deal with pending operations, active
1574231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync, or history.
1575231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1576231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readLegacyAccountInfoLocked() {
1577231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // Look for old database to initialize from.
1578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File file = mContext.getDatabasePath("syncmanager.db");
1579231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (!file.exists()) {
1580231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
1581231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1582231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String path = file.getPath();
1583231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SQLiteDatabase db = null;
1584231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1585231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db = SQLiteDatabase.openDatabase(path, null,
1586231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SQLiteDatabase.OPEN_READONLY);
1587231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (SQLiteException e) {
1588231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1589360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1590231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (db != null) {
15912d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            final boolean hasType = db.getVersion() >= 11;
1592360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1593231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Copy in all of the status information, as well as accounts.
1594231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading legacy sync accounts db");
1595231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
1596231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("stats, status");
1597231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            HashMap<String,String> map = new HashMap<String,String>();
1598231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("_id", "status._id as _id");
1599231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("account", "stats.account as account");
16002d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            if (hasType) {
16012d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                map.put("account_type", "stats.account_type as account_type");
16022d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            }
1603231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("authority", "stats.authority as authority");
1604231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("totalElapsedTime", "totalElapsedTime");
1605231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSyncs", "numSyncs");
1606231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceLocal", "numSourceLocal");
1607231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourcePoll", "numSourcePoll");
1608231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceServer", "numSourceServer");
1609231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceUser", "numSourceUser");
1610231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessSource", "lastSuccessSource");
1611231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessTime", "lastSuccessTime");
1612231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureSource", "lastFailureSource");
1613231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureTime", "lastFailureTime");
1614231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureMesg", "lastFailureMesg");
1615231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("pending", "pending");
1616231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setProjectionMap(map);
1617231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.appendWhere("stats._id = status.stats_id");
1618231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Cursor c = qb.query(db, null, null, null, null, null, null);
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (c.moveToNext()) {
1620231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String accountName = c.getString(c.getColumnIndex("account"));
16212d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                String accountType = hasType
16222d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                        ? c.getString(c.getColumnIndex("account_type")) : null;
16237a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                if (accountType == null) {
16243348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                    accountType = "com.google";
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1626231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String authorityName = c.getString(c.getColumnIndex("authority"));
1627231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = this.getOrCreateAuthorityLocked(
16287a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                        new Account(accountName, accountType),
16297a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                        authorityName, -1, false);
1630231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
1631231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int i = mSyncStatus.size();
1632231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean found = false;
1633231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo st = null;
1634231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (i > 0) {
1635231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        i--;
1636360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                        st = mSyncStatus.valueAt(i);
1637231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (st.authorityId == authority.ident) {
1638231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            found = true;
1639231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
1640231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1641231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1642231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!found) {
1643231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        st = new SyncStatusInfo(authority.ident);
1644231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(authority.ident, st);
1645231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1646231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.totalElapsedTime = getLongColumn(c, "totalElapsedTime");
1647231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSyncs = getIntColumn(c, "numSyncs");
1648231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceLocal = getIntColumn(c, "numSourceLocal");
1649231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourcePoll = getIntColumn(c, "numSourcePoll");
1650231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceServer = getIntColumn(c, "numSourceServer");
1651231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceUser = getIntColumn(c, "numSourceUser");
1652c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    st.numSourcePeriodic = 0;
1653231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessSource = getIntColumn(c, "lastSuccessSource");
1654231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessTime = getLongColumn(c, "lastSuccessTime");
1655231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureSource = getIntColumn(c, "lastFailureSource");
1656231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureTime = getLongColumn(c, "lastFailureTime");
1657231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureMesg = c.getString(c.getColumnIndex("lastFailureMesg"));
1658231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.pending = getIntColumn(c, "pending") != 0;
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1661360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1662231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c.close();
1663360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1664231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Retrieve the settings.
1665231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb = new SQLiteQueryBuilder();
1666231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("settings");
1667231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c = qb.query(db, null, null, null, null, null, null);
1668231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (c.moveToNext()) {
1669231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String name = c.getString(c.getColumnIndex("name"));
1670231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String value = c.getString(c.getColumnIndex("value"));
1671231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name == null) continue;
1672231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name.equals("listen_for_tickles")) {
1673ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    setMasterSyncAutomatically(value == null || Boolean.parseBoolean(value));
1674231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else if (name.startsWith("sync_provider_")) {
1675231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    String provider = name.substring("sync_provider_".length(),
1676231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            name.length());
1677ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    int i = mAuthorities.size();
1678ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    while (i > 0) {
1679ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        i--;
1680360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                        AuthorityInfo authority = mAuthorities.valueAt(i);
1681ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        if (authority.authority.equals(provider)) {
1682ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                            authority.enabled = value == null || Boolean.parseBoolean(value);
16835e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                            authority.syncable = 1;
1684ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        }
1685ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    }
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1688360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.close();
1690360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1691231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db.close();
1692360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1693231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
1694231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeStatusLocked();
1695231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            (new File(path)).delete();
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1698360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1699231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_END = 0;
1700231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_ITEM = 100;
1701360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1702231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1703231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync status back in to the initial engine state.
1704231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1705231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatusLocked() {
1706231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Reading " + mStatusFile.getBaseFile());
1707231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1708231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatusFile.readFully();
1709231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1710231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1711231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1712231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
1713231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATUS_FILE_END) {
1714231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATUS_FILE_ITEM) {
1715231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo status = new SyncStatusInfo(in);
1716231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.indexOfKey(status.authorityId) >= 0) {
1717231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
1718231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (DEBUG_FILE) Log.v(TAG, "Adding status for id "
1719231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                + status.authorityId);
1720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(status.authorityId, status);
1721231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
1723231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
1724231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown status token: " + token);
1725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial status");
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1732360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1733231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1734231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync status to the sync status file.
1735231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1736231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatusLocked() {
1737231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatusFile.getBaseFile());
1738360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1739231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
1740231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
1741231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATUS);
1742360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1743231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1745231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatusFile.startWrite();
1746231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1747231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1748231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1749231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo status = mSyncStatus.valueAt(i);
1750231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATUS_FILE_ITEM);
1751231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.writeToParcel(out, 0);
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1753231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATUS_FILE_END);
1754231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1755231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1756360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1757231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatusFile.finishWrite(fos);
1758231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1759231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing status", e1);
1760231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1761231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatusFile.failWrite(fos);
1762231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1763231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1764231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1765360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1766307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public static final int PENDING_OPERATION_VERSION = 2;
1767360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1768231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1769231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all pending operations back in to the initial engine state.
1770231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1771231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readPendingOperationsLocked() {
1772231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Reading " + mPendingFile.getBaseFile());
1773231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1774231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mPendingFile.readFully();
1775231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1776231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1777231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1778231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int SIZE = in.dataSize();
1779231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (in.dataPosition() < SIZE) {
1780231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int version = in.readInt();
1781307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                if (version != PENDING_OPERATION_VERSION && version != 1) {
1782231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown pending operation version "
1783231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + version + "; dropping all ops");
1784231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1785231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1786231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int authorityId = in.readInt();
1787231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int syncSource = in.readInt();
1788231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                byte[] flatExtras = in.createByteArray();
1789307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                boolean expedited;
1790307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                if (version == PENDING_OPERATION_VERSION) {
1791307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    expedited = in.readInt() != 0;
1792307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                } else {
1793307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    expedited = false;
1794307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                }
1795231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(authorityId);
1796231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
1797231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Bundle extras = null;
1798231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (flatExtras != null) {
1799231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        extras = unflattenBundle(flatExtras);
1800231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1801231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    PendingOperation op = new PendingOperation(
1802231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            authority.account, syncSource,
1803307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            authority.authority, extras, expedited);
1804231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.authorityId = authorityId;
1805231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.flatExtras = flatExtras;
1806231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + op.account
1807231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " auth=" + op.authority
1808231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " src=" + op.syncSource
1809307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            + " expedited=" + op.expedited
1810231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " extras=" + op.extras);
1811231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mPendingOperations.add(op);
1812231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1813231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1814231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1815231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial pending operations");
1816231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1817231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1818360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1819231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writePendingOperationLocked(PendingOperation op, Parcel out) {
1820231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(PENDING_OPERATION_VERSION);
1821231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(op.authorityId);
1822231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(op.syncSource);
1823231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (op.flatExtras == null && op.extras != null) {
1824231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op.flatExtras = flattenBundle(op.extras);
1825231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1826231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeByteArray(op.flatExtras);
1827307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        out.writeInt(op.expedited ? 1 : 0);
1828231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1829360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1830231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1831231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all currently pending ops to the pending ops file.
1832231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1833231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writePendingOperationsLocked() {
1834231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int N = mPendingOperations.size();
1835231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1836231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1837231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (N == 0) {
1838231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG_FILE) Log.v(TAG, "Truncating " + mPendingFile.getBaseFile());
1839231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mPendingFile.truncate();
1840231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
1841231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1842360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1843231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Writing new " + mPendingFile.getBaseFile());
1844231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mPendingFile.startWrite();
1845360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1846231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1847231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1848231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                PendingOperation op = mPendingOperations.get(i);
1849231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationLocked(op, out);
1850231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1851231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1852231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1853360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1854231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingFile.finishWrite(fos);
1855231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1856231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing pending operations", e1);
1857231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1858231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mPendingFile.failWrite(fos);
1859231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1860231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1861231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1862360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1863231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1864231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Append the given operation to the pending ops file; if unable to,
1865231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * write all pending ops.
1866231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1867231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void appendPendingOperationLocked(PendingOperation op) {
1868231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
1869231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1870231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1871231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mPendingFile.openAppend();
1872231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1873231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Failed append; writing full file");
1874231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationsLocked();
1875231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
1876231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1877360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1878231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1879231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1880231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationLocked(op, out);
1881231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1882231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1883231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1884231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing pending operations", e1);
1885231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1886231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            try {
1887231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                fos.close();
1888231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } catch (java.io.IOException e2) {
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1890231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1891231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1892360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1893231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static private byte[] flattenBundle(Bundle bundle) {
1894231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        byte[] flatData = null;
1895231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Parcel parcel = Parcel.obtain();
1896231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1897231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle.writeToParcel(parcel, 0);
1898231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            flatData = parcel.marshall();
1899231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1900231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.recycle();
1901231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1902231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return flatData;
1903231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1904360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1905231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static private Bundle unflattenBundle(byte[] flatData) {
1906231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Bundle bundle;
1907231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Parcel parcel = Parcel.obtain();
1908231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1909231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.unmarshall(flatData, 0, flatData.length);
1910231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.setDataPosition(0);
1911231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle = parcel.readBundle();
1912231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (RuntimeException e) {
1913231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // A RuntimeException is thrown if we were unable to parse the parcel.
1914231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Create an empty parcel in this case.
1915231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle = new Bundle();
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
1917231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.recycle();
1918231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1919231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return bundle;
1920231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1921360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1922231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_END = 0;
1923231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM_OLD = 100;
1924231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM = 101;
1925360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1926231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1927231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync statistics back in to the initial engine state.
1928231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1929231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatisticsLocked() {
1930231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1931231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatisticsFile.readFully();
1932231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1933231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1934231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1935231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
1936231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int index = 0;
1937231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATISTICS_FILE_END) {
1938231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATISTICS_FILE_ITEM
1939231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || token == STATISTICS_FILE_ITEM_OLD) {
1940231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int day = in.readInt();
1941231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (token == STATISTICS_FILE_ITEM_OLD) {
1942231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        day = day - 2009 + 14245;  // Magic!
1943231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1944231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    DayStats ds = new DayStats(day);
1945231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successCount = in.readInt();
1946231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successTime = in.readLong();
1947231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureCount = in.readInt();
1948231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureTime = in.readLong();
1949231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (index < mDayStats.length) {
1950231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mDayStats[index] = ds;
1951231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        index++;
1952231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1953231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
1954231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
1955231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown stats token: " + token);
1956231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1957231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1958231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1959231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1960231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial statistics");
1961231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1962231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1963360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1964231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1965231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync statistics to the sync status file.
1966231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1967231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatisticsLocked() {
1968231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
1969360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1970231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
1971231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
1972231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATISTICS);
1973360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1974231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1975231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1976231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatisticsFile.startWrite();
1977231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1978231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mDayStats.length;
1979231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1980231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                DayStats ds = mDayStats[i];
1981231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ds == null) {
1982231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1983231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1984231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATISTICS_FILE_ITEM);
1985231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.day);
1986231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.successCount);
1987231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.successTime);
1988231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.failureCount);
1989231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.failureTime);
1990231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1991231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATISTICS_FILE_END);
1992231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1993231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1994360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1995231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatisticsFile.finishWrite(fos);
1996231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1997231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing stats", e1);
1998231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1999231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatisticsFile.failWrite(fos);
2000231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2004