SyncStorageEngine.java revision 2269d1572e5fcfb725ea55f5764d8c3280d69f6d
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;
212269d1572e5fcfb725ea55f5764d8c3280d69f6dDianne Hackbornimport com.android.internal.util.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
6351bbcd105a164ebbd69ee3fd1fe8fb75cd8a8c0cbFred Quintana    public AuthorityInfo getOrCreateAuthority(Account account, String authority) {
636231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
6371bbcd105a164ebbd69ee3fd1fe8fb75cd8a8c0cbFred Quintana            return getOrCreateAuthorityLocked(account, authority,
6381bbcd105a164ebbd69ee3fd1fe8fb75cd8a8c0cbFred Quintana                    -1 /* assign a new identifier if creating a new authority */,
6391bbcd105a164ebbd69ee3fd1fe8fb75cd8a8c0cbFred Quintana                    true /* write to storage if this results in a change */);
640231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
642360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
643231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public AuthorityInfo getAuthority(int authorityId) {
644231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
645231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mAuthorities.get(authorityId);
646231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
647231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
648360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
650231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Returns true if there is currently a sync operation for the given
651231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * account or authority in the pending list, or actively being processed.
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6537a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public boolean isSyncActive(Account account, String authority) {
654231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
655231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mPendingOperations.size();
656231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
657231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
658231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // TODO(fredq): this probably shouldn't be considering
659231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // pending operations.
660231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                PendingOperation op = mPendingOperations.get(i);
661231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (op.account.equals(account) && op.authority.equals(authority)) {
662231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
663231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
664231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
665360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
666231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mActiveSync != null) {
667231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = getAuthority(mActiveSync.authorityId);
668231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo != null && ainfo.account.equals(account)
669231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        && ainfo.authority.equals(authority)) {
670231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
671231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
672231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
674360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
675231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
676231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
677360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
678231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public PendingOperation insertIntoPending(PendingOperation op) {
679231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
680231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertIntoPending: account=" + op.account
681231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
682231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
683231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
684360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
685231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getOrCreateAuthorityLocked(op.account,
686231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.authority,
687231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    -1 /* desired identifier */,
688231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    true /* write accounts to storage */);
689231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
690231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return null;
691231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
692360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
693231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op = new PendingOperation(op);
694231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op.authorityId = authority.ident;
695231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.add(op);
696231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            appendPendingOperationLocked(op);
697360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
698231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
699231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.pending = true;
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
701360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
702ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
703231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return op;
704231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
706231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean deleteFromPending(PendingOperation op) {
707231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean res = false;
708231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
709231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "deleteFromPending: account=" + op.account
710231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
711231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
712231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
713231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mPendingOperations.remove(op)) {
714231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mPendingOperations.size() == 0
715231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || mNumPendingFinished >= PENDING_FINISH_TO_WRITE) {
716231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writePendingOperationsLocked();
717231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished = 0;
718231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
719231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished++;
720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
721360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(op.account, op.authority,
723231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "deleteFromPending");
724231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.v(TAG, "removing - " + authority);
726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    final int N = mPendingOperations.size();
727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean morePending = false;
728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (int i=0; i<N; i++) {
729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        PendingOperation cur = mPendingOperations.get(i);
730231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (cur.account.equals(op.account)
731231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                && cur.authority.equals(op.authority)) {
732231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            morePending = true;
733231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
734231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
735231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
736360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
737231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!morePending) {
738231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (DEBUG) Log.v(TAG, "no more pending!");
739231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
740231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
741231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
742231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
743360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
744231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                res = true;
745231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
746231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
747360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
748ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
749231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return res;
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
752231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int clearPending() {
753231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int num;
754231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
755231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "clearPending");
756231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            num = mPendingOperations.size();
757231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.clear();
758231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
759231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
760360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                mSyncStatus.valueAt(i).pending = false;
761231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
762231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationsLocked();
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
764ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
765231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return num;
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
769231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return a copy of the current array of pending operations.  The
770231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * PendingOperation objects are the real objects stored inside, so that
771231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * they can be used with deleteFromPending().
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
773231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<PendingOperation> getPendingOperations() {
774231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
775231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return new ArrayList<PendingOperation>(mPendingOperations);
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
778360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
780231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the number of currently pending operations.
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
782231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int getPendingOperationCount() {
783231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
784231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mPendingOperations.size();
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
787360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
789231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the set of account has changed, given the new array of
790231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active accounts.
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7927a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public void doDatabaseCleanup(Account[] accounts) {
793231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
794231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.w(TAG, "Updating for new accounts...");
795231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SparseArray<AuthorityInfo> removing = new SparseArray<AuthorityInfo>();
796231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Iterator<AccountInfo> accIt = mAccounts.values().iterator();
797231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (accIt.hasNext()) {
798231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AccountInfo acc = accIt.next();
799231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!ArrayUtils.contains(accounts, acc.account)) {
800231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // This account no longer exists...
801231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.w(TAG, "Account removed: " + acc.account);
802231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (AuthorityInfo auth : acc.authorities.values()) {
803231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        removing.put(auth.ident, auth);
804231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
805231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    accIt.remove();
806231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
807231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
808360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
809231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Clean out all data structures.
810231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = removing.size();
811231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (i > 0) {
812231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                while (i > 0) {
813231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    i--;
814231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int ident = removing.keyAt(i);
815231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mAuthorities.remove(ident);
816231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int j = mSyncStatus.size();
817231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
818231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
819231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncStatus.keyAt(j) == ident) {
820231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncStatus.remove(mSyncStatus.keyAt(j));
821231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
822231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
823231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    j = mSyncHistory.size();
824231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
825231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
826231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncHistory.get(j).authorityId == ident) {
827231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncHistory.remove(j);
828231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
829231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
830231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
831231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
832231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
833231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationsLocked();
834231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
835231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
840231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the currently active sync is changing (there can only be
841231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * one at a time).  Either supply a valid ActiveSyncContext with information
842231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * about the sync, or null to stop the currently active sync.
843231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
844231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void setActiveSync(SyncManager.ActiveSyncContext activeSyncContext) {
845231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
846231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (activeSyncContext != null) {
847231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: account="
848231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + activeSyncContext.mSyncOperation.account
849231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " auth=" + activeSyncContext.mSyncOperation.authority
850231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " src=" + activeSyncContext.mSyncOperation.syncSource
851231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " extras=" + activeSyncContext.mSyncOperation.extras);
852231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mActiveSync != null) {
853231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "setActiveSync called with existing active sync!");
854231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
855231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(
856231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.account,
857231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.authority,
858231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "setActiveSync");
859231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority == null) {
860231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return;
861231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
862231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = new ActiveSyncInfo(authority.ident,
863231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        authority.account, authority.authority,
864231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mStartTime);
865231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else {
866231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: null");
867231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = null;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
870360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
871ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
874231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
875231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * To allow others to send active change reports, to poke clients.
876231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
877231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void reportActiveChange() {
878ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
879231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
880360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
881231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
882231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Note that sync has started for the given account and authority.
883231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
8847a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public long insertStartSyncEvent(Account accountName, String authorityName,
885231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long now, int source) {
886231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long id;
887231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
888231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertStartSyncEvent: account=" + accountName
889231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + authorityName + " source=" + source);
890231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getAuthorityLocked(accountName, authorityName,
891231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    "insertStartSyncEvent");
892231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
893231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return -1;
894231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
895231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = new SyncHistoryItem();
896231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.authorityId = authority.ident;
897231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.historyId = mNextHistoryId++;
898231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mNextHistoryId < 0) mNextHistoryId = 0;
899231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.eventTime = now;
900231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.source = source;
901231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_START;
902231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncHistory.add(0, item);
903231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (mSyncHistory.size() > MAX_HISTORY) {
904231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mSyncHistory.remove(mSyncHistory.size()-1);
905231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
906231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            id = item.historyId;
907231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "returning historyId " + id);
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
909360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
910ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
911231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return id;
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
914c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public static boolean equals(Bundle b1, Bundle b2) {
915c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (b1.size() != b2.size()) {
916c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return false;
917c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
918c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (b1.isEmpty()) {
919c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return true;
920c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
921c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        for (String key : b1.keySet()) {
922c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (!b2.containsKey(key)) {
923c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                return false;
924c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
925c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (!b1.get(key).equals(b2.get(key))) {
926c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                return false;
927c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
928c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
929c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return true;
930c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
931c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
932c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public void stopSyncEvent(long historyId, Bundle extras, long elapsedTime, String resultMessage,
933231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long downstreamActivity, long upstreamActivity) {
934231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
935231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "stopSyncEvent: historyId=" + historyId);
936231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = null;
937231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncHistory.size();
938231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
939231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
940231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = mSyncHistory.get(i);
941231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (item.historyId == historyId) {
942231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
943231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
944231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = null;
945231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
946360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
947231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (item == null) {
948231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, "stopSyncEvent: no history for id " + historyId);
949231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
950231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
951360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
952231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.elapsedTime = elapsedTime;
953231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_STOP;
954231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.mesg = resultMessage;
955231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.downstreamActivity = downstreamActivity;
956231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.upstreamActivity = upstreamActivity;
957360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
958231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(item.authorityId);
959360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
960231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.numSyncs++;
961231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.totalElapsedTime += elapsedTime;
962231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            switch (item.source) {
963231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_LOCAL:
964231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceLocal++;
965231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
966231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_POLL:
967231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourcePoll++;
968231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
969231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_USER:
970231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceUser++;
971231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
972231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_SERVER:
973231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceServer++;
974231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
975c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                case SOURCE_PERIODIC:
976c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    status.numSourcePeriodic++;
977c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    AuthorityInfo authority = mAuthorities.get(item.authorityId);
978c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    for (int periodicSyncIndex = 0;
979c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            periodicSyncIndex < authority.periodicSyncs.size();
980c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            periodicSyncIndex++) {
981c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        if (equals(extras, authority.periodicSyncs.get(periodicSyncIndex).first)) {
982c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            status.setPeriodicSyncTime(periodicSyncIndex, item.eventTime);
983c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        }
984c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    }
985c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    break;
986231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
987360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
988231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatisticsNow = false;
98955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            int day = getCurrentDayLocked();
990231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mDayStats[0] == null) {
991231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
992231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (day != mDayStats[0].day) {
993231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                System.arraycopy(mDayStats, 0, mDayStats, 1, mDayStats.length-1);
994231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
995231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsNow = true;
996231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (mDayStats[0] == null) {
997231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
998231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final DayStats ds = mDayStats[0];
999360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1000231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final long lastSyncTime = (item.eventTime + elapsedTime);
1001231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatusNow = false;
1002231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (MESG_SUCCESS.equals(resultMessage)) {
1003231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // - if successful, update the successful columns
1004231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastSuccessTime == 0 || status.lastFailureTime != 0) {
1005231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
1006231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1007231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessTime = lastSyncTime;
1008231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessSource = item.source;
1009231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = 0;
1010231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = -1;
1011231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = null;
1012231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.initialFailureTime = 0;
1013231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successCount++;
1014231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successTime += elapsedTime;
1015231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!MESG_CANCELED.equals(resultMessage)) {
1016231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastFailureTime == 0) {
1017231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
1018231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1019231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = lastSyncTime;
1020231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = item.source;
1021231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = resultMessage;
1022231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.initialFailureTime == 0) {
1023231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.initialFailureTime = lastSyncTime;
1024231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1025231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureCount++;
1026231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureTime += elapsedTime;
1027231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1028360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1029231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatusNow) {
1030231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
1031231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATUS)) {
1032231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATUS),
1033231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATUS_DELAY);
1034231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1035231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatisticsNow) {
1036231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
1037231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATISTICS)) {
1038231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATISTICS),
1039231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATISTICS_DELAY);
1040360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache            }
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1042360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1043ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1047231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the currently active sync information, or null if there is no
1048231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active sync.  Note that the returned object is the real, live active
1049231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync object, so be careful what you do with it.
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1051231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ActiveSyncInfo getActiveSync() {
1052231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1053231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mActiveSync;
1054231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1056360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1057231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1058231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
1059231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1060231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1061231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1062231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncStatusInfo> getSyncStatus() {
1063231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1064231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1065231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncStatusInfo> ops = new ArrayList<SyncStatusInfo>(N);
1066231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1067231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ops.add(mSyncStatus.valueAt(i));
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1069231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ops;
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1072360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1073231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1074c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * Return an array of the current authorities. Note
1075c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * that the objects inside the array are the real, live objects,
1076c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * so be careful what you do with them.
1077c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     */
1078c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public ArrayList<AuthorityInfo> getAuthorities() {
1079c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
1080c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            final int N = mAuthorities.size();
1081c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            ArrayList<AuthorityInfo> infos = new ArrayList<AuthorityInfo>(N);
1082c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            for (int i=0; i<N; i++) {
1083c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                infos.add(mAuthorities.valueAt(i));
1084c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1085c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return infos;
1086c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1087c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1088c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1089c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /**
1090b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     * Returns the status that matches the authority and account.
1091b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     *
1092b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     * @param account the account we want to check
1093231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authority the authority whose row should be selected
1094c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * @return the SyncStatusInfo for the authority
1095231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1096b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache    public SyncStatusInfo getStatusByAccountAndAuthority(Account account, String authority) {
1097b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache        if (account == null || authority == null) {
1098b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache          throw new IllegalArgumentException();
1099b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache        }
1100231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1101231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1103360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                SyncStatusInfo cur = mSyncStatus.valueAt(i);
1104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
1105b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
1106b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                if (ainfo != null && ainfo.authority.equals(authority) &&
1107b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                    account.equals(ainfo.account)) {
1108b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                  return cur;
1109231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1111b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache            return null;
1112231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1114360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1115231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return true if the pending status is true of any matching authorities.
1117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1118ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean isSyncPending(Account account, String authority) {
1119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1120231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1121231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1122360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                SyncStatusInfo cur = mSyncStatus.valueAt(i);
1123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
1124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo == null) {
1125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
1126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (account != null && !ainfo.account.equals(account)) {
1128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
1129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo.authority.equals(authority) && cur.pending) {
1131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1134231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
1140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncHistoryItem> getSyncHistory() {
1144231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1145231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncHistory.size();
1146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncHistoryItem> items = new ArrayList<SyncHistoryItem>(N);
1147231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                items.add(mSyncHistory.get(i));
1149231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1150231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return items;
1151231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1152231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1153360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1154231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1155231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current per-day statistics.  Note
1156231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1157231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1158231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1159231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public DayStats[] getDayStatistics() {
1160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            DayStats[] ds = new DayStats[mDayStats.length];
1162231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            System.arraycopy(mDayStats, 0, ds, 0, ds.length);
1163231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ds;
1164231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1165231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1166360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1167231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If sync is failing for any of the provider/accounts then determine the time at which it
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * started failing and return the earliest time over all the provider/accounts. If none are
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * failing then return 0.
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getInitialSyncFailureTime() {
1173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1174ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (!mMasterSyncAutomatically) {
1175231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return 0;
1176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1177360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long oldest = 0;
1179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncStatus.size();
1180231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
1181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
1182231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo stats = mSyncStatus.valueAt(i);
1183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(stats.authorityId);
1184231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null && authority.enabled) {
1185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (oldest == 0 || stats.initialFailureTime < oldest) {
1186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        oldest = stats.initialFailureTime;
1187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1188231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1190360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1191231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return oldest;
1192231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1193231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1194360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
119555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private int getCurrentDayLocked() {
1196231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal.setTimeInMillis(System.currentTimeMillis());
1197231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
1198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (mYear != mCal.get(Calendar.YEAR)) {
1199231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYear = mCal.get(Calendar.YEAR);
1200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.clear();
1201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.set(Calendar.YEAR, mYear);
1202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYearInDays = (int)(mCal.getTimeInMillis()/86400000);
1203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return dayOfYear + mYearInDays;
1205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1206360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1207231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Retrieve an authority, returning null if one does not exist.
1209360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache     *
1210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param accountName The name of the account for the authority.
1211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authorityName The name of the authority itself.
1212231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param tag If non-null, this will be used in a log message if the
1213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * requested authority does not exist.
1214231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
12157a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private AuthorityInfo getAuthorityLocked(Account accountName, String authorityName,
1216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tag) {
1217231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
1218231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
1219231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
1220b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
1221b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                    Log.v(TAG, tag + ": unknown account " + accountName);
1222b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                }
1223231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1224231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
1225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1226231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
1227231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
1228231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
1229b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
1230b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                    Log.v(TAG, tag + ": unknown authority " + authorityName);
1231b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                }
1232231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1233231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
1234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1235360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
1237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1238360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
12397a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private AuthorityInfo getOrCreateAuthorityLocked(Account accountName,
1240231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String authorityName, int ident, boolean doWrite) {
1241231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
1242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
1243231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account = new AccountInfo(accountName);
1244231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccounts.put(accountName, account);
1245231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1246231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
1247231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
1248231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (ident < 0) {
1249231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // Look for a new identifier for this authority.
1250231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                final int N = mAuthorities.size();
1251231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ident = 0;
1252231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                for (int i=0; i<N; i++) {
1253231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.valueAt(i).ident > ident) {
1254231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        break;
1255231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1256231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ident++;
1257231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1258231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1259bd0a81ff1c0e92e80e05e2f12bb1805c7d081e94Dianne Hackborn            if (DEBUG) Log.v(TAG, "created a new AuthorityInfo for " + accountName
1260b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                    + ", provider " + authorityName);
1261231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            authority = new AuthorityInfo(accountName, authorityName, ident);
1262231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account.authorities.put(authorityName, authority);
1263231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAuthorities.put(ident, authority);
1264231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (doWrite) {
1265231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
1266231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1267231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1268360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1269231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
1270231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1271360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1272c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public SyncStatusInfo getOrCreateSyncStatus(AuthorityInfo authority) {
1273c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
1274c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return getOrCreateSyncStatusLocked(authority.ident);
1275c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1276c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1277c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1278231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private SyncStatusInfo getOrCreateSyncStatusLocked(int authorityId) {
1279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SyncStatusInfo status = mSyncStatus.get(authorityId);
1280231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (status == null) {
1281231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status = new SyncStatusInfo(authorityId);
1282231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncStatus.put(authorityId, status);
1283231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1284231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return status;
1285231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1286360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
128755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    public void writeAllState() {
128855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        synchronized (mAuthorities) {
128955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Account info is always written so no need to do it here.
1290360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
129155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            if (mNumPendingFinished > 0) {
129255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                // Only write these if they are out of date.
129355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                writePendingOperationsLocked();
129455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
1295360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
129655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Just always write these...  they are likely out of date.
129755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatusLocked();
129855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatisticsLocked();
129955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
130055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
1301360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1302231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1303c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * public for testing
1304c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     */
1305c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public void clearAndReadState() {
1306c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
1307c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mAuthorities.clear();
1308c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mAccounts.clear();
1309c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mPendingOperations.clear();
1310c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mSyncStatus.clear();
1311c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mSyncHistory.clear();
1312c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1313c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readAccountInfoLocked();
1314c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readStatusLocked();
1315c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readPendingOperationsLocked();
1316c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readStatisticsLocked();
1317c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readLegacyAccountInfoLocked();
1318c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1319c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1320c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1321c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /**
1322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all account information back in to the initial engine state.
1323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readAccountInfoLocked() {
1325231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileInputStream fis = null;
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fis = mAccountInfoFile.openRead();
1328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading " + mAccountInfoFile.getBaseFile());
1329231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlPullParser parser = Xml.newPullParser();
1330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parser.setInput(fis, null);
1331231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int eventType = parser.getEventType();
1332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (eventType != XmlPullParser.START_TAG) {
1333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tagName = parser.getName();
1336231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if ("accounts".equals(tagName)) {
1337231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String listen = parser.getAttributeValue(
1338231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        null, "listen-for-tickles");
1339ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                mMasterSyncAutomatically = listen == null
1340231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            || Boolean.parseBoolean(listen);
1341231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1342c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                AuthorityInfo authority = null;
1343c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                Pair<Bundle, Long> periodicSync = null;
1344231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                do {
1345c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    if (eventType == XmlPullParser.START_TAG) {
1346231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        tagName = parser.getName();
1347c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        if (parser.getDepth() == 2) {
1348c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            if ("authority".equals(tagName)) {
1349c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                authority = parseAuthority(parser);
1350c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                periodicSync = null;
1351231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1352c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (parser.getDepth() == 3) {
1353c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            if ("periodicSync".equals(tagName) && authority != null) {
1354c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                periodicSync = parsePeriodicSync(parser, authority);
1355c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            }
1356c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (parser.getDepth() == 4 && periodicSync != null) {
1357c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            if ("extra".equals(tagName)) {
1358c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                parseExtra(parser, periodicSync);
1359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1360231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1362231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    eventType = parser.next();
1363231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } while (eventType != XmlPullParser.END_DOCUMENT);
1364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (XmlPullParserException e) {
1366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error reading accounts", e);
1367231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1368231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis == null) Log.i(TAG, "No initial accounts");
1369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            else Log.w(TAG, "Error reading accounts", e);
1370231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis != null) {
1372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
1373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    fis.close();
1374231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (java.io.IOException e1) {
1375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1376231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1379360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1380c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private AuthorityInfo parseAuthority(XmlPullParser parser) {
1381c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        AuthorityInfo authority = null;
1382c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        int id = -1;
1383c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
1384c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            id = Integer.parseInt(parser.getAttributeValue(
1385c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    null, "id"));
1386c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NumberFormatException e) {
1387c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing the id of the authority", e);
1388c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NullPointerException e) {
1389c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "the id of the authority is null", e);
1390c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1391c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (id >= 0) {
1392c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String accountName = parser.getAttributeValue(null, "account");
1393c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String accountType = parser.getAttributeValue(null, "type");
1394c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (accountType == null) {
1395c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                accountType = "com.google";
1396c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1397c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String authorityName = parser.getAttributeValue(null, "authority");
1398c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String enabled = parser.getAttributeValue(null, "enabled");
1399c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String syncable = parser.getAttributeValue(null, "syncable");
1400c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            authority = mAuthorities.get(id);
1401c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (DEBUG_FILE) Log.v(TAG, "Adding authority: account="
1402c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    + accountName + " auth=" + authorityName
1403c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    + " enabled=" + enabled
1404c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    + " syncable=" + syncable);
1405c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (authority == null) {
1406c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                if (DEBUG_FILE) Log.v(TAG, "Creating entry");
1407c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                authority = getOrCreateAuthorityLocked(
1408c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        new Account(accountName, accountType), authorityName, id, false);
1409c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                // clear this since we will read these later on
1410c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                authority.periodicSyncs.clear();
1411c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1412c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (authority != null) {
1413c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                authority.enabled = enabled == null || Boolean.parseBoolean(enabled);
1414c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                if ("unknown".equals(syncable)) {
1415c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    authority.syncable = -1;
1416c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                } else {
1417c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    authority.syncable =
1418c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            (syncable == null || Boolean.parseBoolean(enabled)) ? 1 : 0;
1419c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
1420c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else {
1421c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                Log.w(TAG, "Failure adding authority: account="
1422c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        + accountName + " auth=" + authorityName
1423c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        + " enabled=" + enabled
1424c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        + " syncable=" + syncable);
1425c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1426c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1427c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1428c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return authority;
1429c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1430c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1431c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private Pair<Bundle, Long> parsePeriodicSync(XmlPullParser parser, AuthorityInfo authority) {
1432c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        Bundle extras = new Bundle();
1433c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String periodValue = parser.getAttributeValue(null, "period");
1434c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        final long period;
1435c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
1436c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            period = Long.parseLong(periodValue);
1437c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NumberFormatException e) {
1438c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing the period of a periodic sync", e);
1439c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return null;
1440c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NullPointerException e) {
1441c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "the period of a periodic sync is null", e);
1442c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return null;
1443c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1444c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        final Pair<Bundle, Long> periodicSync = Pair.create(extras, period);
1445c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        authority.periodicSyncs.add(periodicSync);
1446c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return periodicSync;
1447c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1448c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1449c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private void parseExtra(XmlPullParser parser, Pair<Bundle, Long> periodicSync) {
1450c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        final Bundle extras = periodicSync.first;
1451c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String name = parser.getAttributeValue(null, "name");
1452c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String type = parser.getAttributeValue(null, "type");
1453c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String value1 = parser.getAttributeValue(null, "value1");
1454c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String value2 = parser.getAttributeValue(null, "value2");
1455c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1456c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
1457c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if ("long".equals(type)) {
1458c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putLong(name, Long.parseLong(value1));
1459c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("integer".equals(type)) {
1460c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putInt(name, Integer.parseInt(value1));
1461c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("double".equals(type)) {
1462c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putDouble(name, Double.parseDouble(value1));
1463c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("float".equals(type)) {
1464c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putFloat(name, Float.parseFloat(value1));
1465c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("boolean".equals(type)) {
1466c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putBoolean(name, Boolean.parseBoolean(value1));
1467c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("string".equals(type)) {
1468c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putString(name, value1);
1469c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("account".equals(type)) {
1470c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putParcelable(name, new Account(value1, value2));
1471c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1472c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NumberFormatException e) {
1473c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing bundle value", e);
1474c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NullPointerException e) {
1475c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing bundle value", e);
1476c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1477c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1478c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1479231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1480231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all account information to the account file.
1481231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1482231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeAccountInfoLocked() {
1483231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
1484231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1485360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1486231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1487231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mAccountInfoFile.startWrite();
1488231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlSerializer out = new FastXmlSerializer();
1489231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setOutput(fos, "utf-8");
1490231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startDocument(null, true);
1491231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1492360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1493231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startTag(null, "accounts");
1494ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (!mMasterSyncAutomatically) {
1495231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "listen-for-tickles", "false");
1496231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1497360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1498231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mAuthorities.size();
1499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1500360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                AuthorityInfo authority = mAuthorities.valueAt(i);
1501231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.startTag(null, "authority");
1502231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "id", Integer.toString(authority.ident));
1503ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                out.attribute(null, "account", authority.account.name);
1504ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                out.attribute(null, "type", authority.account.type);
1505231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "authority", authority.authority);
1506231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!authority.enabled) {
1507231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    out.attribute(null, "enabled", "false");
1508231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
15095e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                if (authority.syncable < 0) {
15105e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    out.attribute(null, "syncable", "unknown");
15115e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                } else if (authority.syncable == 0) {
15125e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    out.attribute(null, "syncable", "false");
15135e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
1514c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                for (Pair<Bundle, Long> periodicSync : authority.periodicSyncs) {
1515c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    out.startTag(null, "periodicSync");
1516c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    out.attribute(null, "period", Long.toString(periodicSync.second));
1517c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    final Bundle extras = periodicSync.first;
1518c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    for (String key : extras.keySet()) {
1519c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        out.startTag(null, "extra");
1520c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        out.attribute(null, "name", key);
1521c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        final Object value = extras.get(key);
1522c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        if (value instanceof Long) {
1523c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "long");
1524c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1525c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Integer) {
1526c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "integer");
1527c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1528c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Boolean) {
1529c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "boolean");
1530c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1531c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Float) {
1532c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "float");
1533c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1534c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Double) {
1535c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "double");
1536c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1537c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof String) {
1538c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "string");
1539c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", value.toString());
1540c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (value instanceof Account) {
1541c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "type", "account");
1542c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value1", ((Account)value).name);
1543c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            out.attribute(null, "value2", ((Account)value).type);
1544c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        }
1545c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        out.endTag(null, "extra");
1546c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    }
1547c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    out.endTag(null, "periodicSync");
1548c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
1549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.endTag(null, "authority");
1550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1551360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1552231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endTag(null, "accounts");
1553360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1554231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endDocument();
1555360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1556231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccountInfoFile.finishWrite(fos);
1557231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1558231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing accounts", e1);
1559231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1560231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mAccountInfoFile.failWrite(fos);
1561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1562231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1564360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static int getIntColumn(Cursor c, String name) {
1566231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getInt(c.getColumnIndex(name));
1567231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1568360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1569231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static long getLongColumn(Cursor c, String name) {
1570231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getLong(c.getColumnIndex(name));
1571231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1572360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1573231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1574231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Load sync engine state from the old syncmanager database, and then
1575231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * erase it.  Note that we don't deal with pending operations, active
1576231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync, or history.
1577231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readLegacyAccountInfoLocked() {
1579231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // Look for old database to initialize from.
1580231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File file = mContext.getDatabasePath("syncmanager.db");
1581231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (!file.exists()) {
1582231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
1583231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1584231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String path = file.getPath();
1585231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SQLiteDatabase db = null;
1586231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1587231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db = SQLiteDatabase.openDatabase(path, null,
1588231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SQLiteDatabase.OPEN_READONLY);
1589231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (SQLiteException e) {
1590231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1591360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1592231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (db != null) {
15932d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            final boolean hasType = db.getVersion() >= 11;
1594360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1595231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Copy in all of the status information, as well as accounts.
1596231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading legacy sync accounts db");
1597231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
1598231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("stats, status");
1599231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            HashMap<String,String> map = new HashMap<String,String>();
1600231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("_id", "status._id as _id");
1601231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("account", "stats.account as account");
16022d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            if (hasType) {
16032d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                map.put("account_type", "stats.account_type as account_type");
16042d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            }
1605231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("authority", "stats.authority as authority");
1606231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("totalElapsedTime", "totalElapsedTime");
1607231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSyncs", "numSyncs");
1608231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceLocal", "numSourceLocal");
1609231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourcePoll", "numSourcePoll");
1610231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceServer", "numSourceServer");
1611231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceUser", "numSourceUser");
1612231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessSource", "lastSuccessSource");
1613231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessTime", "lastSuccessTime");
1614231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureSource", "lastFailureSource");
1615231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureTime", "lastFailureTime");
1616231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureMesg", "lastFailureMesg");
1617231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("pending", "pending");
1618231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setProjectionMap(map);
1619231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.appendWhere("stats._id = status.stats_id");
1620231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Cursor c = qb.query(db, null, null, null, null, null, null);
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (c.moveToNext()) {
1622231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String accountName = c.getString(c.getColumnIndex("account"));
16232d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                String accountType = hasType
16242d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                        ? c.getString(c.getColumnIndex("account_type")) : null;
16257a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                if (accountType == null) {
16263348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                    accountType = "com.google";
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1628231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String authorityName = c.getString(c.getColumnIndex("authority"));
1629231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = this.getOrCreateAuthorityLocked(
16307a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                        new Account(accountName, accountType),
16317a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                        authorityName, -1, false);
1632231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
1633231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int i = mSyncStatus.size();
1634231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean found = false;
1635231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo st = null;
1636231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (i > 0) {
1637231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        i--;
1638360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                        st = mSyncStatus.valueAt(i);
1639231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (st.authorityId == authority.ident) {
1640231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            found = true;
1641231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
1642231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1643231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1644231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!found) {
1645231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        st = new SyncStatusInfo(authority.ident);
1646231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(authority.ident, st);
1647231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1648231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.totalElapsedTime = getLongColumn(c, "totalElapsedTime");
1649231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSyncs = getIntColumn(c, "numSyncs");
1650231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceLocal = getIntColumn(c, "numSourceLocal");
1651231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourcePoll = getIntColumn(c, "numSourcePoll");
1652231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceServer = getIntColumn(c, "numSourceServer");
1653231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceUser = getIntColumn(c, "numSourceUser");
1654c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    st.numSourcePeriodic = 0;
1655231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessSource = getIntColumn(c, "lastSuccessSource");
1656231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessTime = getLongColumn(c, "lastSuccessTime");
1657231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureSource = getIntColumn(c, "lastFailureSource");
1658231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureTime = getLongColumn(c, "lastFailureTime");
1659231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureMesg = c.getString(c.getColumnIndex("lastFailureMesg"));
1660231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.pending = getIntColumn(c, "pending") != 0;
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1663360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1664231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c.close();
1665360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1666231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Retrieve the settings.
1667231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb = new SQLiteQueryBuilder();
1668231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("settings");
1669231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c = qb.query(db, null, null, null, null, null, null);
1670231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (c.moveToNext()) {
1671231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String name = c.getString(c.getColumnIndex("name"));
1672231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String value = c.getString(c.getColumnIndex("value"));
1673231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name == null) continue;
1674231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name.equals("listen_for_tickles")) {
1675ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    setMasterSyncAutomatically(value == null || Boolean.parseBoolean(value));
1676231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else if (name.startsWith("sync_provider_")) {
1677231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    String provider = name.substring("sync_provider_".length(),
1678231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            name.length());
1679ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    int i = mAuthorities.size();
1680ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    while (i > 0) {
1681ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        i--;
1682360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                        AuthorityInfo authority = mAuthorities.valueAt(i);
1683ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        if (authority.authority.equals(provider)) {
1684ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                            authority.enabled = value == null || Boolean.parseBoolean(value);
16855e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                            authority.syncable = 1;
1686ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        }
1687ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    }
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1690360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.close();
1692360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1693231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db.close();
1694360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1695231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
1696231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeStatusLocked();
1697231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            (new File(path)).delete();
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1700360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1701231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_END = 0;
1702231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_ITEM = 100;
1703360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1704231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1705231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync status back in to the initial engine state.
1706231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1707231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatusLocked() {
1708231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Reading " + mStatusFile.getBaseFile());
1709231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1710231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatusFile.readFully();
1711231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1712231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1713231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1714231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
1715231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATUS_FILE_END) {
1716231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATUS_FILE_ITEM) {
1717231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo status = new SyncStatusInfo(in);
1718231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.indexOfKey(status.authorityId) >= 0) {
1719231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
1720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (DEBUG_FILE) Log.v(TAG, "Adding status for id "
1721231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                + status.authorityId);
1722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(status.authorityId, status);
1723231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1724231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
1725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
1726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown status token: " + token);
1727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1730231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1731231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial status");
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1734360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1735231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1736231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync status to the sync status file.
1737231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1738231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatusLocked() {
1739231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatusFile.getBaseFile());
1740360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1741231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
1742231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
1743231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATUS);
1744360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1745231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1747231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatusFile.startWrite();
1748231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1749231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1750231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1751231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo status = mSyncStatus.valueAt(i);
1752231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATUS_FILE_ITEM);
1753231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.writeToParcel(out, 0);
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1755231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATUS_FILE_END);
1756231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1757231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1758360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1759231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatusFile.finishWrite(fos);
1760231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1761231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing status", e1);
1762231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1763231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatusFile.failWrite(fos);
1764231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1765231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1766231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1767360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1768307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public static final int PENDING_OPERATION_VERSION = 2;
1769360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1770231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1771231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all pending operations back in to the initial engine state.
1772231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1773231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readPendingOperationsLocked() {
1774231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Reading " + mPendingFile.getBaseFile());
1775231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1776231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mPendingFile.readFully();
1777231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1778231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1779231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1780231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int SIZE = in.dataSize();
1781231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (in.dataPosition() < SIZE) {
1782231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int version = in.readInt();
1783307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                if (version != PENDING_OPERATION_VERSION && version != 1) {
1784231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown pending operation version "
1785231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + version + "; dropping all ops");
1786231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1787231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1788231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int authorityId = in.readInt();
1789231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int syncSource = in.readInt();
1790231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                byte[] flatExtras = in.createByteArray();
1791307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                boolean expedited;
1792307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                if (version == PENDING_OPERATION_VERSION) {
1793307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    expedited = in.readInt() != 0;
1794307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                } else {
1795307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    expedited = false;
1796307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                }
1797231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(authorityId);
1798231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
1799231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Bundle extras = null;
1800231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (flatExtras != null) {
1801231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        extras = unflattenBundle(flatExtras);
1802231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1803231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    PendingOperation op = new PendingOperation(
1804231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            authority.account, syncSource,
1805307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            authority.authority, extras, expedited);
1806231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.authorityId = authorityId;
1807231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.flatExtras = flatExtras;
1808231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + op.account
1809231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " auth=" + op.authority
1810231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " src=" + op.syncSource
1811307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            + " expedited=" + op.expedited
1812231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " extras=" + op.extras);
1813231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mPendingOperations.add(op);
1814231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1815231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1816231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1817231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial pending operations");
1818231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1819231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1820360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1821231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writePendingOperationLocked(PendingOperation op, Parcel out) {
1822231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(PENDING_OPERATION_VERSION);
1823231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(op.authorityId);
1824231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(op.syncSource);
1825231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (op.flatExtras == null && op.extras != null) {
1826231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op.flatExtras = flattenBundle(op.extras);
1827231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1828231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeByteArray(op.flatExtras);
1829307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        out.writeInt(op.expedited ? 1 : 0);
1830231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1831360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1832231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1833231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all currently pending ops to the pending ops file.
1834231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1835231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writePendingOperationsLocked() {
1836231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int N = mPendingOperations.size();
1837231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1838231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1839231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (N == 0) {
1840231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG_FILE) Log.v(TAG, "Truncating " + mPendingFile.getBaseFile());
1841231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mPendingFile.truncate();
1842231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
1843231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1844360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1845231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Writing new " + mPendingFile.getBaseFile());
1846231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mPendingFile.startWrite();
1847360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1848231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1849231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1850231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                PendingOperation op = mPendingOperations.get(i);
1851231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationLocked(op, out);
1852231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1853231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1854231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1855360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1856231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingFile.finishWrite(fos);
1857231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1858231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing pending operations", e1);
1859231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1860231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mPendingFile.failWrite(fos);
1861231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1862231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1863231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1864360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1865231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1866231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Append the given operation to the pending ops file; if unable to,
1867231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * write all pending ops.
1868231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1869231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void appendPendingOperationLocked(PendingOperation op) {
1870231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
1871231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1872231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1873231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mPendingFile.openAppend();
1874231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1875231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Failed append; writing full file");
1876231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationsLocked();
1877231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
1878231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1879360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1880231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1881231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1882231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationLocked(op, out);
1883231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1884231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1885231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1886231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing pending operations", e1);
1887231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1888231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            try {
1889231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                fos.close();
1890231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } catch (java.io.IOException e2) {
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1892231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1893231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1894360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1895231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static private byte[] flattenBundle(Bundle bundle) {
1896231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        byte[] flatData = null;
1897231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Parcel parcel = Parcel.obtain();
1898231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1899231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle.writeToParcel(parcel, 0);
1900231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            flatData = parcel.marshall();
1901231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1902231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.recycle();
1903231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1904231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return flatData;
1905231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1906360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1907231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static private Bundle unflattenBundle(byte[] flatData) {
1908231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Bundle bundle;
1909231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Parcel parcel = Parcel.obtain();
1910231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1911231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.unmarshall(flatData, 0, flatData.length);
1912231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.setDataPosition(0);
1913231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle = parcel.readBundle();
1914231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (RuntimeException e) {
1915231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // A RuntimeException is thrown if we were unable to parse the parcel.
1916231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Create an empty parcel in this case.
1917231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle = new Bundle();
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
1919231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.recycle();
1920231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1921231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return bundle;
1922231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1923360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1924231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_END = 0;
1925231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM_OLD = 100;
1926231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM = 101;
1927360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1928231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1929231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync statistics back in to the initial engine state.
1930231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1931231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatisticsLocked() {
1932231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1933231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatisticsFile.readFully();
1934231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1935231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1936231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1937231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
1938231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int index = 0;
1939231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATISTICS_FILE_END) {
1940231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATISTICS_FILE_ITEM
1941231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || token == STATISTICS_FILE_ITEM_OLD) {
1942231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int day = in.readInt();
1943231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (token == STATISTICS_FILE_ITEM_OLD) {
1944231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        day = day - 2009 + 14245;  // Magic!
1945231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1946231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    DayStats ds = new DayStats(day);
1947231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successCount = in.readInt();
1948231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successTime = in.readLong();
1949231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureCount = in.readInt();
1950231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureTime = in.readLong();
1951231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (index < mDayStats.length) {
1952231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mDayStats[index] = ds;
1953231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        index++;
1954231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1955231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
1956231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
1957231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown stats token: " + token);
1958231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1959231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1960231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1961231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1962231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial statistics");
1963231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1964231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1965360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1966231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1967231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync statistics to the sync status file.
1968231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1969231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatisticsLocked() {
1970231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
1971360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1972231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
1973231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
1974231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATISTICS);
1975360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1976231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1977231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1978231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatisticsFile.startWrite();
1979231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1980231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mDayStats.length;
1981231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1982231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                DayStats ds = mDayStats[i];
1983231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ds == null) {
1984231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1985231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1986231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATISTICS_FILE_ITEM);
1987231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.day);
1988231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.successCount);
1989231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.successTime);
1990231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.failureCount);
1991231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.failureTime);
1992231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1993231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATISTICS_FILE_END);
1994231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1995231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1996360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1997231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatisticsFile.finishWrite(fos);
1998231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1999231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing stats", e1);
2000231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
2001231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatisticsFile.failWrite(fos);
2002231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2006