SyncStorageEngine.java revision 307da1a46b4c9b711bafe8fbaaa6b98e8868c18e
1231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn/*
2231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Copyright (C) 2009 The Android Open Source Project
3231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn *
4231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * you may not use this file except in compliance with the License.
6231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * You may obtain a copy of the License at
7231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn *
8231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn *
10231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * See the License for the specific language governing permissions and
14231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * limitations under the License.
15231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn */
16231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.content;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport com.android.internal.os.AtomicFile;
20231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport com.android.internal.util.ArrayUtils;
21d4a4729c0cac582a2dcec7c8cfb316b81885a0f0Tom Taylorimport com.android.common.FastXmlSerializer;
22231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
23231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport org.xmlpull.v1.XmlPullParser;
24231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
25231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport org.xmlpull.v1.XmlSerializer;
26231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
27d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintanaimport android.accounts.Account;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
30231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.database.sqlite.SQLiteException;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder;
32231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Bundle;
33231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Environment;
34231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Handler;
35231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Message;
36231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel;
37231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteCallbackList;
38231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteException;
39307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanaimport android.os.SystemClock;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
41231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.SparseArray;
42231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.Xml;
43307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanaimport android.util.Pair;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
45231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.File;
46231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileInputStream;
47231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileOutputStream;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
49231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Calendar;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
51231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Iterator;
52231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.TimeZone;
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
65231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // @VisibleForTesting
66231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
68231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync start event. */
69231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_START = 0;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
71231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync stop event. */
72231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_STOP = 1;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
74231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
75231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync event types. */
76231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] EVENTS = { "START", "STOP" };
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a server-initiated sync. */
79231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_SERVER = 0;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
81231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a local-initiated sync. */
82231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_LOCAL = 1;
83231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
84231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Enum value for a poll-based sync (e.g., upon connection to
85231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * network)
86231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
87231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_POLL = 2;
88231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
89231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a user-initiated sync. */
90231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_USER = 3;
91231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
92307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public static final long NOT_IN_BACKOFF_MODE = -1;
93307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
94ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    private static final Intent SYNC_CONNECTION_SETTING_CHANGED_INTENT =
95ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
96ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
97231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
98231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync source types. */
99231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] SOURCES = { "SERVER",
100231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "LOCAL",
101231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "POLL",
102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "USER" };
103231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // The MESG column will contain one of these or one of the Error types.
105231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_SUCCESS = "success";
106231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_CANCELED = "canceled";
107231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
108a33e3f79259b56b03c7912af35944f34ad190e3cDianne Hackborn    public static final int MAX_HISTORY = 100;
109360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATUS = 1;
111231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATUS_DELAY = 1000*60*10; // 10 minutes
112360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
113231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATISTICS = 2;
114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATISTICS_DELAY = 1000*60*30; // 1/2 hour
1158294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato
1168294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato    private static final boolean SYNC_ENABLED_DEFAULT = false;
117360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class PendingOperation {
1197a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
120231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int syncSource;
121231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String authority;
122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final Bundle extras;        // note: read-only.
123307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        final boolean expedited;
124360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int authorityId;
126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        byte[] flatExtras;
127360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1287a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        PendingOperation(Account account, int source,
129307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                String authority, Bundle extras, boolean expedited) {
130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = source;
132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = authority;
133231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = extras != null ? new Bundle(extras) : extras;
134307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            this.expedited = expedited;
135231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authorityId = -1;
136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        PendingOperation(PendingOperation other) {
139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = other.account;
140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = other.syncSource;
141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = other.authority;
142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = other.extras;
143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authorityId = other.authorityId;
144307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            this.expedited = other.expedited;
145231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
147360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static class AccountInfo {
1497a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
150231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final HashMap<String, AuthorityInfo> authorities =
151231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                new HashMap<String, AuthorityInfo>();
152360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1537a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        AccountInfo(Account account) {
154231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
155231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
156231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
157360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
158231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class AuthorityInfo {
1597a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String authority;
161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int ident;
162231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean enabled;
1635e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        int syncable;
164307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        long backoffTime;
165307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        long backoffDelay;
166307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        long delayUntil;
167ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
1687a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        AuthorityInfo(Account account, String authority, int ident) {
169231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
170231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = authority;
171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.ident = ident;
1728294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            enabled = SYNC_ENABLED_DEFAULT;
1734a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana            syncable = -1; // default to "unknown"
174307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            backoffTime = -1; // if < 0 then we aren't in backoff mode
175307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            backoffDelay = -1; // if < 0 then we aren't in backoff mode
176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
178360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class SyncHistoryItem {
180231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int authorityId;
181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int historyId;
182231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long eventTime;
183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long elapsedTime;
184231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int source;
185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int event;
186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long upstreamActivity;
187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long downstreamActivity;
188231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String mesg;
189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
190360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
191231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class DayStats {
192231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public final int day;
193231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int successCount;
194231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long successTime;
195231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int failureCount;
196231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long failureTime;
197360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public DayStats(int day) {
199231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.day = day;
200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
202360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // Primary list of all syncable authorities.  Also our global lock.
204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<AuthorityInfo> mAuthorities =
205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<AuthorityInfo>();
206360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2077a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private final HashMap<Account, AccountInfo> mAccounts =
2087a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        new HashMap<Account, AccountInfo>();
209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<PendingOperation> mPendingOperations =
211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<PendingOperation>();
212360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private ActiveSyncInfo mActiveSync;
214360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<SyncStatusInfo> mSyncStatus =
216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<SyncStatusInfo>();
217360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
218231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<SyncHistoryItem> mSyncHistory =
219231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<SyncHistoryItem>();
220360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
221231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final RemoteCallbackList<ISyncStatusObserver> mChangeListeners
222231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            = new RemoteCallbackList<ISyncStatusObserver>();
223360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
224231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // We keep 4 weeks of stats.
225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final DayStats[] mDayStats = new DayStats[7*4];
226231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Calendar mCal;
227231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYear;
228231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYearInDays;
229360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
230231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Context mContext;
231231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static volatile SyncStorageEngine sSyncStorageEngine = null;
232360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
233231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the core engine state: all accounts and the
235231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * settings for them.  It must never be lost, and should be changed
236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * infrequently, so it is stored as an XML file.
237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
238231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mAccountInfoFile;
239360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
240231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
241231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the current sync status.  We would like to retain
242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * it across boots, but its loss is not the end of the world, so we store
243231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * this information as binary data.
244231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
245231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatusFile;
246360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
247231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
248231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains sync statistics.  This is purely debugging information
249231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so is written infrequently and can be thrown away at any time.
250231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
251231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatisticsFile;
252360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
253231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
254231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the pending sync operations.  It is a binary file,
255231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * which must be updated every time an operation is added or removed,
256231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so we have special handling of it.
257231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
258231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mPendingFile;
259231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int PENDING_FINISH_TO_WRITE = 4;
260231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNumPendingFinished = 0;
261360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
262231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNextHistoryId = 0;
263ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    private boolean mMasterSyncAutomatically = true;
264360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SyncStorageEngine(Context context) {
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sSyncStorageEngine = this;
268360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
269231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
270360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
271a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor        // This call will return the correct directory whether Encrypted File Systems is
272a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor        // enabled or not.
273a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor        File dataDir = Environment.getSecureDataDirectory();
274231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File systemDir = new File(dataDir, "system");
275231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File syncDir = new File(systemDir, "sync");
276231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
277231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
278231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mPendingFile = new AtomicFile(new File(syncDir, "pending.bin"));
279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
280360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
281231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readAccountInfoLocked();
282231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatusLocked();
283231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readPendingOperationsLocked();
284231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatisticsLocked();
285231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readLegacyAccountInfoLocked();
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine newTestInstance(Context context) {
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new SyncStorageEngine(context);
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void init(Context context) {
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine != null) {
294307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            return;
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sSyncStorageEngine = new SyncStorageEngine(context);
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine getSingleton() {
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine == null) {
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("not initialized");
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sSyncStorageEngine;
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
306231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    @Override public void handleMessage(Message msg) {
307231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (msg.what == MSG_WRITE_STATUS) {
308231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            synchronized (mAccounts) {
309231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
310231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
311231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } else if (msg.what == MSG_WRITE_STATISTICS) {
312231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            synchronized (mAccounts) {
313231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
316231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
317360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
318231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
319231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.register(callback, mask);
321231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
323360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void removeStatusChangeListener(ISyncStatusObserver callback) {
325231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
326231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.unregister(callback);
327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
329360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void reportChange(int which) {
331231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        ArrayList<ISyncStatusObserver> reports = null;
332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mChangeListeners.beginBroadcast();
334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
336231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Integer mask = (Integer)mChangeListeners.getBroadcastCookie(i);
337231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if ((which & mask.intValue()) == 0) {
338231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
339231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
340231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (reports == null) {
341231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports = new ArrayList<ISyncStatusObserver>(i);
342231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
343231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                reports.add(mChangeListeners.getBroadcastItem(i));
344231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
345b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            mChangeListeners.finishBroadcast();
346231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
347360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
348231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG) Log.v(TAG, "reportChange " + which + " to: " + reports);
349360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
350231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (reports != null) {
351231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = reports.size();
352231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
353231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
354231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
355231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports.get(i).onStatusChanged(which);
356231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (RemoteException e) {
357231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // The remote callback list will take care of this for us.
358231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
360231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
36270c874ba20b586712a7550b6c5efeb6dc0fdf9faAmith Yamasani
363ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getSyncAutomatically(Account account, String providerName) {
364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (account != null) {
366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(account, providerName,
367ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        "getSyncAutomatically");
368ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return authority != null && authority.enabled;
369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
370ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mAuthorities.size();
372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
374360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                AuthorityInfo authority = mAuthorities.valueAt(i);
375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority.authority.equals(providerName)
376231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        && authority.enabled) {
377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
380231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
384ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setSyncAutomatically(Account account, String providerName, boolean sync) {
3858294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        boolean wasEnabled;
386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
3878294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
3888294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            wasEnabled = authority.enabled;
3898294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            authority.enabled = sync;
390231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3928294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato
3938294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        if (!wasEnabled && sync) {
394307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            ContentResolver.requestSync(account, providerName, new Bundle());
3958294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        }
396ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3995e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    public int getIsSyncable(Account account, String providerName) {
4005e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        synchronized (mAuthorities) {
4015e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            if (account != null) {
4025e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                AuthorityInfo authority = getAuthorityLocked(account, providerName,
4035e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                        "getIsSyncable");
4045e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                if (authority == null) {
4055e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    return -1;
4065e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
4075e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                return authority.syncable;
4085e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
4095e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
4105e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            int i = mAuthorities.size();
4115e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            while (i > 0) {
4125e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                i--;
413360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                AuthorityInfo authority = mAuthorities.valueAt(i);
4145e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                if (authority.authority.equals(providerName)) {
4155e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    return authority.syncable;
4165e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
4175e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
4185e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            return -1;
4195e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
4205e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
4215e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
4225e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    public void setIsSyncable(Account account, String providerName, int syncable) {
4235e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        int oldState;
424b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana        if (syncable > 1) {
425b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana            syncable = 1;
426b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana        } else if (syncable < -1) {
427b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana            syncable = -1;
428b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana        }
429b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana        Log.d(TAG, "setIsSyncable: " + account + ", provider " + providerName + " -> " + syncable);
4305e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        synchronized (mAuthorities) {
4315e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
4325e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            oldState = authority.syncable;
4335e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            authority.syncable = syncable;
4345e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            writeAccountInfoLocked();
4355e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
4365e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
4375e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        if (oldState <= 0 && syncable > 0) {
438307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            ContentResolver.requestSync(account, providerName, new Bundle());
4395e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
4405e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
4415e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
4425e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
443307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public Pair<Long, Long> getBackoff(Account account, String providerName) {
444307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
445307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            AuthorityInfo authority = getAuthorityLocked(account, providerName, "getBackoff");
446307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            if (authority == null || authority.backoffTime < 0) {
447307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                return null;
448307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
449307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            return Pair.create(authority.backoffTime, authority.backoffDelay);
450307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
451307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
452307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
453307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public void setBackoff(Account account, String providerName,
454307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            long nextSyncTime, long nextDelay) {
455307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
456307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            Log.v(TAG, "setBackoff: " + account + ", provider " + providerName
457307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    + " -> nextSyncTime " + nextSyncTime + ", nextDelay " + nextDelay);
458307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
459307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        boolean changed = false;
460307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
461307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            if (account == null || providerName == null) {
462307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                for (AccountInfo accountInfo : mAccounts.values()) {
463307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    if (account != null && !account.equals(accountInfo.account)) continue;
464307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
465307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                        if (providerName != null && !providerName.equals(authorityInfo.authority)) {
466307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            continue;
467307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                        }
468307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                        if (authorityInfo.backoffTime != nextSyncTime
469307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                                || authorityInfo.backoffDelay != nextDelay) {
470307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            authorityInfo.backoffTime = nextSyncTime;
471307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            authorityInfo.backoffDelay = nextDelay;
472307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            changed = true;
473307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                        }
474307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    }
475307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                }
476307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            } else {
477307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                AuthorityInfo authority =
478307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                        getOrCreateAuthorityLocked(account, providerName, -1, false);
479307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                if (authority.backoffTime == nextSyncTime && authority.backoffDelay == nextDelay) {
480307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    return;
481307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                }
482307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                authority.backoffTime = nextSyncTime;
483307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                authority.backoffDelay = nextDelay;
484307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                changed = true;
485307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
486307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            if (changed) {
487307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                writeAccountInfoLocked();
488307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
489307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
490307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
491307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        if (changed) {
492307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
493307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
494307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
495307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
496307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public void setDelayUntilTime(Account account, String providerName, long delayUntil) {
497307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
498307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            Log.v(TAG, "setDelayUntil: " + account + ", provider " + providerName
499307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    + " -> delayUntil " + delayUntil);
500307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
501307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
502307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
503307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            if (authority.delayUntil == delayUntil) {
504307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                return;
505307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
506307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            authority.delayUntil = delayUntil;
507307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            writeAccountInfoLocked();
508307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
509307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
510307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
511307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
512307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
513307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public long getDelayUntilTime(Account account, String providerName) {
514307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
515307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            AuthorityInfo authority = getAuthorityLocked(account, providerName, "getDelayUntil");
516307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            if (authority == null) {
517307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                return 0;
518307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
519307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            return authority.delayUntil;
520307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
521307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
522307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
523ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setMasterSyncAutomatically(boolean flag) {
5248294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        boolean old;
525231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
5268294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            old = mMasterSyncAutomatically;
527ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            mMasterSyncAutomatically = flag;
528231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5308294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        if (!old && flag) {
531307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            ContentResolver.requestSync(null, null, new Bundle());
5328294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        }
533ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
534ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        mContext.sendBroadcast(SYNC_CONNECTION_SETTING_CHANGED_INTENT);
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
537ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getMasterSyncAutomatically() {
538231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
539ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            return mMasterSyncAutomatically;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
542360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
5437a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public AuthorityInfo getAuthority(Account account, String authority) {
544231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
545231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return getAuthorityLocked(account, authority, null);
546231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
548360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public AuthorityInfo getAuthority(int authorityId) {
550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
551231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mAuthorities.get(authorityId);
552231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
553231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
554360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
556231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Returns true if there is currently a sync operation for the given
557231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * account or authority in the pending list, or actively being processed.
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5597a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public boolean isSyncActive(Account account, String authority) {
560231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mPendingOperations.size();
562231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // TODO(fredq): this probably shouldn't be considering
565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // pending operations.
566231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                PendingOperation op = mPendingOperations.get(i);
567231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (op.account.equals(account) && op.authority.equals(authority)) {
568231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
569231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
570231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
571360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
572231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mActiveSync != null) {
573231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = getAuthority(mActiveSync.authorityId);
574231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo != null && ainfo.account.equals(account)
575231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        && ainfo.authority.equals(authority)) {
576231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
577231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
580360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
581231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
582231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
583360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
584231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public PendingOperation insertIntoPending(PendingOperation op) {
585231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
586231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertIntoPending: account=" + op.account
587231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
588231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
589231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
590360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
591231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getOrCreateAuthorityLocked(op.account,
592231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.authority,
593231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    -1 /* desired identifier */,
594231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    true /* write accounts to storage */);
595231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
596231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return null;
597231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
598360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
599231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op = new PendingOperation(op);
600231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op.authorityId = authority.ident;
601231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.add(op);
602231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            appendPendingOperationLocked(op);
603360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
604231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
605231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.pending = true;
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
607360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
608ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
609231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return op;
610231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
612231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean deleteFromPending(PendingOperation op) {
613231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean res = false;
614231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
615231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "deleteFromPending: account=" + op.account
616231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
617231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
618231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
619231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mPendingOperations.remove(op)) {
620231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mPendingOperations.size() == 0
621231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || mNumPendingFinished >= PENDING_FINISH_TO_WRITE) {
622231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writePendingOperationsLocked();
623231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished = 0;
624231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
625231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished++;
626231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
627360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
628231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(op.account, op.authority,
629231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "deleteFromPending");
630231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
631231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.v(TAG, "removing - " + authority);
632231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    final int N = mPendingOperations.size();
633231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean morePending = false;
634231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (int i=0; i<N; i++) {
635231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        PendingOperation cur = mPendingOperations.get(i);
636231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (cur.account.equals(op.account)
637231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                && cur.authority.equals(op.authority)) {
638231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            morePending = true;
639231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
640231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
641231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
642360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
643231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!morePending) {
644231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (DEBUG) Log.v(TAG, "no more pending!");
645231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
646231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
647231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
648231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
649360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
650231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                res = true;
651231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
652231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
653360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
654ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
655231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return res;
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
658231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int clearPending() {
659231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int num;
660231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
661231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "clearPending");
662231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            num = mPendingOperations.size();
663231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.clear();
664231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
665231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
666360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                mSyncStatus.valueAt(i).pending = false;
667231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
668231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationsLocked();
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
670ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
671231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return num;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
675231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return a copy of the current array of pending operations.  The
676231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * PendingOperation objects are the real objects stored inside, so that
677231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * they can be used with deleteFromPending().
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
679231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<PendingOperation> getPendingOperations() {
680231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
681231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return new ArrayList<PendingOperation>(mPendingOperations);
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
684360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
686231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the number of currently pending operations.
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
688231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int getPendingOperationCount() {
689231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
690231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mPendingOperations.size();
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
693360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
695231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the set of account has changed, given the new array of
696231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active accounts.
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6987a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public void doDatabaseCleanup(Account[] accounts) {
699231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
700231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.w(TAG, "Updating for new accounts...");
701231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SparseArray<AuthorityInfo> removing = new SparseArray<AuthorityInfo>();
702231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Iterator<AccountInfo> accIt = mAccounts.values().iterator();
703231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (accIt.hasNext()) {
704231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AccountInfo acc = accIt.next();
705231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!ArrayUtils.contains(accounts, acc.account)) {
706231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // This account no longer exists...
707231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.w(TAG, "Account removed: " + acc.account);
708231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (AuthorityInfo auth : acc.authorities.values()) {
709231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        removing.put(auth.ident, auth);
710231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
711231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    accIt.remove();
712231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
713231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
714360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
715231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Clean out all data structures.
716231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = removing.size();
717231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (i > 0) {
718231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                while (i > 0) {
719231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    i--;
720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int ident = removing.keyAt(i);
721231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mAuthorities.remove(ident);
722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int j = mSyncStatus.size();
723231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
724231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncStatus.keyAt(j) == ident) {
726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncStatus.remove(mSyncStatus.keyAt(j));
727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    j = mSyncHistory.size();
730231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
731231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
732231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncHistory.get(j).authorityId == ident) {
733231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncHistory.remove(j);
734231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
735231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
736231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
737231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
738231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
739231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationsLocked();
740231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
741231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
745231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
746231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the currently active sync is changing (there can only be
747231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * one at a time).  Either supply a valid ActiveSyncContext with information
748231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * about the sync, or null to stop the currently active sync.
749231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
750231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void setActiveSync(SyncManager.ActiveSyncContext activeSyncContext) {
751231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
752231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (activeSyncContext != null) {
753231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: account="
754231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + activeSyncContext.mSyncOperation.account
755231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " auth=" + activeSyncContext.mSyncOperation.authority
756231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " src=" + activeSyncContext.mSyncOperation.syncSource
757231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " extras=" + activeSyncContext.mSyncOperation.extras);
758231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mActiveSync != null) {
759231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "setActiveSync called with existing active sync!");
760231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
761231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(
762231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.account,
763231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.authority,
764231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "setActiveSync");
765231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority == null) {
766231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return;
767231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
768231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = new ActiveSyncInfo(authority.ident,
769231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        authority.account, authority.authority,
770231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mStartTime);
771231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else {
772231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: null");
773231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = null;
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
776360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
777ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
780231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
781231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * To allow others to send active change reports, to poke clients.
782231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
783231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void reportActiveChange() {
784ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
785231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
786360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
787231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
788231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Note that sync has started for the given account and authority.
789231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
7907a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public long insertStartSyncEvent(Account accountName, String authorityName,
791231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long now, int source) {
792231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long id;
793231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
794231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertStartSyncEvent: account=" + accountName
795231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + authorityName + " source=" + source);
796231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getAuthorityLocked(accountName, authorityName,
797231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    "insertStartSyncEvent");
798231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
799231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return -1;
800231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
801231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = new SyncHistoryItem();
802231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.authorityId = authority.ident;
803231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.historyId = mNextHistoryId++;
804231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mNextHistoryId < 0) mNextHistoryId = 0;
805231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.eventTime = now;
806231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.source = source;
807231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_START;
808231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncHistory.add(0, item);
809231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (mSyncHistory.size() > MAX_HISTORY) {
810231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mSyncHistory.remove(mSyncHistory.size()-1);
811231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
812231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            id = item.historyId;
813231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "returning historyId " + id);
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
815360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
816ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
817231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return id;
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
820231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
821231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long downstreamActivity, long upstreamActivity) {
822231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
823231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "stopSyncEvent: historyId=" + historyId);
824231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = null;
825231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncHistory.size();
826231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
827231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
828231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = mSyncHistory.get(i);
829231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (item.historyId == historyId) {
830231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
831231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
832231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = null;
833231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
834360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
835231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (item == null) {
836231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, "stopSyncEvent: no history for id " + historyId);
837231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
838231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
839360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
840231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.elapsedTime = elapsedTime;
841231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_STOP;
842231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.mesg = resultMessage;
843231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.downstreamActivity = downstreamActivity;
844231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.upstreamActivity = upstreamActivity;
845360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
846231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(item.authorityId);
847360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
848231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.numSyncs++;
849231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.totalElapsedTime += elapsedTime;
850231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            switch (item.source) {
851231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_LOCAL:
852231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceLocal++;
853231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
854231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_POLL:
855231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourcePoll++;
856231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
857231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_USER:
858231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceUser++;
859231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
860231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_SERVER:
861231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceServer++;
862231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
863231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
864360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
865231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatisticsNow = false;
86655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            int day = getCurrentDayLocked();
867231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mDayStats[0] == null) {
868231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
869231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (day != mDayStats[0].day) {
870231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                System.arraycopy(mDayStats, 0, mDayStats, 1, mDayStats.length-1);
871231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
872231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsNow = true;
873231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (mDayStats[0] == null) {
874231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
875231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final DayStats ds = mDayStats[0];
876360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
877231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final long lastSyncTime = (item.eventTime + elapsedTime);
878231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatusNow = false;
879231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (MESG_SUCCESS.equals(resultMessage)) {
880231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // - if successful, update the successful columns
881231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastSuccessTime == 0 || status.lastFailureTime != 0) {
882231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
883231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
884231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessTime = lastSyncTime;
885231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessSource = item.source;
886231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = 0;
887231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = -1;
888231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = null;
889231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.initialFailureTime = 0;
890231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successCount++;
891231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successTime += elapsedTime;
892231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!MESG_CANCELED.equals(resultMessage)) {
893231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastFailureTime == 0) {
894231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
895231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
896231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = lastSyncTime;
897231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = item.source;
898231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = resultMessage;
899231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.initialFailureTime == 0) {
900231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.initialFailureTime = lastSyncTime;
901231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
902231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureCount++;
903231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureTime += elapsedTime;
904231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
905360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
906231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatusNow) {
907231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
908231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATUS)) {
909231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATUS),
910231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATUS_DELAY);
911231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
912231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatisticsNow) {
913231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
914231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATISTICS)) {
915231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATISTICS),
916231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATISTICS_DELAY);
917360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache            }
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
919360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
920ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
924231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the currently active sync information, or null if there is no
925231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active sync.  Note that the returned object is the real, live active
926231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync object, so be careful what you do with it.
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
928231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ActiveSyncInfo getActiveSync() {
929231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
930231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mActiveSync;
931231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
933360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
934231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
935231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
936231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
937231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
938231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
939231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncStatusInfo> getSyncStatus() {
940231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
941231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
942231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncStatusInfo> ops = new ArrayList<SyncStatusInfo>(N);
943231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
944231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ops.add(mSyncStatus.valueAt(i));
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
946231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ops;
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
949360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
950231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
951b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     * Returns the status that matches the authority and account.
952b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     *
953b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     * @param account the account we want to check
954231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authority the authority whose row should be selected
955231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @return the SyncStatusInfo for the authority, or null if none exists
956231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
957b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache    public SyncStatusInfo getStatusByAccountAndAuthority(Account account, String authority) {
958b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache        if (account == null || authority == null) {
959b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache          throw new IllegalArgumentException();
960b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache        }
961231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
962231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
963231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
964360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                SyncStatusInfo cur = mSyncStatus.valueAt(i);
965231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
966b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache
967b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                if (ainfo != null && ainfo.authority.equals(authority) &&
968b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                    account.equals(ainfo.account)) {
969b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                  return cur;
970231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
971231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
972b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache            return null;
973231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
975360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
976231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
977231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return true if the pending status is true of any matching authorities.
978231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
979ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean isSyncPending(Account account, String authority) {
980231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
981231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
982231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
983360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                SyncStatusInfo cur = mSyncStatus.valueAt(i);
984231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
985231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo == null) {
986231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
987231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
988231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (account != null && !ainfo.account.equals(account)) {
989231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
990231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
991231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo.authority.equals(authority) && cur.pending) {
992231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
995231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1000231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
1001231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1002231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1003231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1004231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncHistoryItem> getSyncHistory() {
1005231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1006231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncHistory.size();
1007231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncHistoryItem> items = new ArrayList<SyncHistoryItem>(N);
1008231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1009231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                items.add(mSyncHistory.get(i));
1010231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1011231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return items;
1012231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1013231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1014360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1015231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1016231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current per-day statistics.  Note
1017231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1018231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1019231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1020231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public DayStats[] getDayStatistics() {
1021231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1022231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            DayStats[] ds = new DayStats[mDayStats.length];
1023231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            System.arraycopy(mDayStats, 0, ds, 0, ds.length);
1024231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ds;
1025231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1026231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1027360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1028231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If sync is failing for any of the provider/accounts then determine the time at which it
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * started failing and return the earliest time over all the provider/accounts. If none are
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * failing then return 0.
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getInitialSyncFailureTime() {
1034231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1035ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (!mMasterSyncAutomatically) {
1036231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return 0;
1037231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1038360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1039231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long oldest = 0;
1040231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncStatus.size();
1041231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
1042231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
1043231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo stats = mSyncStatus.valueAt(i);
1044231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(stats.authorityId);
1045231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null && authority.enabled) {
1046231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (oldest == 0 || stats.initialFailureTime < oldest) {
1047231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        oldest = stats.initialFailureTime;
1048231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1049231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1050231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1051360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1052231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return oldest;
1053231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1054231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1055360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
105655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private int getCurrentDayLocked() {
1057231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal.setTimeInMillis(System.currentTimeMillis());
1058231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
1059231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (mYear != mCal.get(Calendar.YEAR)) {
1060231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYear = mCal.get(Calendar.YEAR);
1061231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.clear();
1062231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.set(Calendar.YEAR, mYear);
1063231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYearInDays = (int)(mCal.getTimeInMillis()/86400000);
1064231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1065231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return dayOfYear + mYearInDays;
1066231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1067360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1068231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1069231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Retrieve an authority, returning null if one does not exist.
1070360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache     *
1071231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param accountName The name of the account for the authority.
1072231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authorityName The name of the authority itself.
1073231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param tag If non-null, this will be used in a log message if the
1074231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * requested authority does not exist.
1075231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
10767a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private AuthorityInfo getAuthorityLocked(Account accountName, String authorityName,
1077231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tag) {
1078231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
1079231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
1080231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
1081b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
1082b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                    Log.v(TAG, tag + ": unknown account " + accountName);
1083b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                }
1084231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1085231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
1086231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1087231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
1088231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
1089231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
1090b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
1091b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                    Log.v(TAG, tag + ": unknown authority " + authorityName);
1092b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                }
1093231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1094231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
1095231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1096360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1097231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
1098231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1099360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
11007a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private AuthorityInfo getOrCreateAuthorityLocked(Account accountName,
1101231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String authorityName, int ident, boolean doWrite) {
1102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
1103231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
1104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account = new AccountInfo(accountName);
1105231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccounts.put(accountName, account);
1106231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1107231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
1108231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
1109231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (ident < 0) {
1110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // Look for a new identifier for this authority.
1111231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                final int N = mAuthorities.size();
1112231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ident = 0;
1113231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                for (int i=0; i<N; i++) {
1114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.valueAt(i).ident > ident) {
1115231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        break;
1116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ident++;
1118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1120bd0a81ff1c0e92e80e05e2f12bb1805c7d081e94Dianne Hackborn            if (DEBUG) Log.v(TAG, "created a new AuthorityInfo for " + accountName
1121b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                    + ", provider " + authorityName);
1122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            authority = new AuthorityInfo(accountName, authorityName, ident);
1123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account.authorities.put(authorityName, authority);
1124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAuthorities.put(ident, authority);
1125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (doWrite) {
1126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
1127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1129360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
1131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1132360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1133231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private SyncStatusInfo getOrCreateSyncStatusLocked(int authorityId) {
1134231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SyncStatusInfo status = mSyncStatus.get(authorityId);
1135231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (status == null) {
1136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status = new SyncStatusInfo(authorityId);
1137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncStatus.put(authorityId, status);
1138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return status;
1140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1141360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
114255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    public void writeAllState() {
114355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        synchronized (mAuthorities) {
114455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Account info is always written so no need to do it here.
1145360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
114655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            if (mNumPendingFinished > 0) {
114755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                // Only write these if they are out of date.
114855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                writePendingOperationsLocked();
114955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
1150360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
115155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Just always write these...  they are likely out of date.
115255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatusLocked();
115355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatisticsLocked();
115455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
115555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
1156360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1157231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1158231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all account information back in to the initial engine state.
1159231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readAccountInfoLocked() {
1161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileInputStream fis = null;
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1163231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fis = mAccountInfoFile.openRead();
1164231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading " + mAccountInfoFile.getBaseFile());
1165231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlPullParser parser = Xml.newPullParser();
1166231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parser.setInput(fis, null);
1167231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int eventType = parser.getEventType();
1168231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (eventType != XmlPullParser.START_TAG) {
1169231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1170231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tagName = parser.getName();
1172231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if ("accounts".equals(tagName)) {
1173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String listen = parser.getAttributeValue(
1174231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        null, "listen-for-tickles");
1175ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                mMasterSyncAutomatically = listen == null
1176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            || Boolean.parseBoolean(listen);
1177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                do {
1179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (eventType == XmlPullParser.START_TAG
1180231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            && parser.getDepth() == 2) {
1181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        tagName = parser.getName();
1182231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if ("authority".equals(tagName)) {
1183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            int id = -1;
1184231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            try {
1185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                id = Integer.parseInt(parser.getAttributeValue(
1186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "id"));
1187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            } catch (NumberFormatException e) {
1188231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            } catch (NullPointerException e) {
1189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1190231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            if (id >= 0) {
1191231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                String accountName = parser.getAttributeValue(
1192231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "account");
11937a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                String accountType = parser.getAttributeValue(
11947a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                        null, "type");
11957a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                if (accountType == null) {
11963348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                                    accountType = "com.google";
11977a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                }
1198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                String authorityName = parser.getAttributeValue(
1199231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "authority");
1200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                String enabled = parser.getAttributeValue(
1201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "enabled");
12025e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                String syncable = parser.getAttributeValue(null, "syncable");
12035e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                AuthorityInfo authority = mAuthorities.get(id);
1204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                if (DEBUG_FILE) Log.v(TAG, "Adding authority: account="
1205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        + accountName + " auth=" + authorityName
12065e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                        + " enabled=" + enabled
12075e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                        + " syncable=" + syncable);
1208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                if (authority == null) {
1209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    if (DEBUG_FILE) Log.v(TAG, "Creating entry");
1210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    authority = getOrCreateAuthorityLocked(
12117a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                            new Account(accountName, accountType),
12127a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                            authorityName, id, false);
1213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                }
1214231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                if (authority != null) {
1215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    authority.enabled = enabled == null
1216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                            || Boolean.parseBoolean(enabled);
12175e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                    if ("unknown".equals(syncable)) {
12185e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                        authority.syncable = -1;
12195e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                    } else {
12205e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                        authority.syncable =
12215e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                                (syncable == null || Boolean.parseBoolean(enabled))
12225e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                                        ? 1
12235e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                                        : 0;
12245e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                    }
1225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                } else {
1226231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    Log.w(TAG, "Failure adding authority: account="
1227231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                            + accountName + " auth=" + authorityName
12285e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                            + " enabled=" + enabled
12295e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                                            + " syncable=" + syncable);
1230231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                }
1231231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1232231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1233231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    eventType = parser.next();
1235231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } while (eventType != XmlPullParser.END_DOCUMENT);
1236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (XmlPullParserException e) {
1238231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error reading accounts", e);
1239231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1240231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis == null) Log.i(TAG, "No initial accounts");
1241231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            else Log.w(TAG, "Error reading accounts", e);
1242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1243231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis != null) {
1244231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
1245231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    fis.close();
1246231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (java.io.IOException e1) {
1247231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1248231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1249231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1250231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1251360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1252231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1253231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all account information to the account file.
1254231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1255231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeAccountInfoLocked() {
1256231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
1257231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1258360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1259231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1260231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mAccountInfoFile.startWrite();
1261231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlSerializer out = new FastXmlSerializer();
1262231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setOutput(fos, "utf-8");
1263231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startDocument(null, true);
1264231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1265360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1266231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startTag(null, "accounts");
1267ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (!mMasterSyncAutomatically) {
1268231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "listen-for-tickles", "false");
1269231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1270360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1271231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mAuthorities.size();
1272231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1273360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                AuthorityInfo authority = mAuthorities.valueAt(i);
1274231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.startTag(null, "authority");
1275231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "id", Integer.toString(authority.ident));
1276ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                out.attribute(null, "account", authority.account.name);
1277ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                out.attribute(null, "type", authority.account.type);
1278231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "authority", authority.authority);
1279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!authority.enabled) {
1280231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    out.attribute(null, "enabled", "false");
1281231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
12825e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                if (authority.syncable < 0) {
12835e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    out.attribute(null, "syncable", "unknown");
12845e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                } else if (authority.syncable == 0) {
12855e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    out.attribute(null, "syncable", "false");
12865e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
1287231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.endTag(null, "authority");
1288231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1289360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1290231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endTag(null, "accounts");
1291360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1292231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endDocument();
1293360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1294231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccountInfoFile.finishWrite(fos);
1295231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1296231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing accounts", e1);
1297231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1298231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mAccountInfoFile.failWrite(fos);
1299231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1300231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1301231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1302360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1303231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static int getIntColumn(Cursor c, String name) {
1304231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getInt(c.getColumnIndex(name));
1305231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1306360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1307231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static long getLongColumn(Cursor c, String name) {
1308231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getLong(c.getColumnIndex(name));
1309231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1310360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1311231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1312231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Load sync engine state from the old syncmanager database, and then
1313231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * erase it.  Note that we don't deal with pending operations, active
1314231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync, or history.
1315231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1316231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readLegacyAccountInfoLocked() {
1317231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // Look for old database to initialize from.
1318231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File file = mContext.getDatabasePath("syncmanager.db");
1319231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (!file.exists()) {
1320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
1321231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String path = file.getPath();
1323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SQLiteDatabase db = null;
1324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1325231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db = SQLiteDatabase.openDatabase(path, null,
1326231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SQLiteDatabase.OPEN_READONLY);
1327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (SQLiteException e) {
1328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1329360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (db != null) {
13312d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            final boolean hasType = db.getVersion() >= 11;
1332360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Copy in all of the status information, as well as accounts.
1334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading legacy sync accounts db");
1335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
1336231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("stats, status");
1337231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            HashMap<String,String> map = new HashMap<String,String>();
1338231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("_id", "status._id as _id");
1339231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("account", "stats.account as account");
13402d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            if (hasType) {
13412d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                map.put("account_type", "stats.account_type as account_type");
13422d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            }
1343231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("authority", "stats.authority as authority");
1344231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("totalElapsedTime", "totalElapsedTime");
1345231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSyncs", "numSyncs");
1346231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceLocal", "numSourceLocal");
1347231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourcePoll", "numSourcePoll");
1348231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceServer", "numSourceServer");
1349231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceUser", "numSourceUser");
1350231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessSource", "lastSuccessSource");
1351231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessTime", "lastSuccessTime");
1352231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureSource", "lastFailureSource");
1353231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureTime", "lastFailureTime");
1354231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureMesg", "lastFailureMesg");
1355231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("pending", "pending");
1356231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setProjectionMap(map);
1357231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.appendWhere("stats._id = status.stats_id");
1358231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Cursor c = qb.query(db, null, null, null, null, null, null);
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (c.moveToNext()) {
1360231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String accountName = c.getString(c.getColumnIndex("account"));
13612d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                String accountType = hasType
13622d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                        ? c.getString(c.getColumnIndex("account_type")) : null;
13637a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                if (accountType == null) {
13643348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                    accountType = "com.google";
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String authorityName = c.getString(c.getColumnIndex("authority"));
1367231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = this.getOrCreateAuthorityLocked(
13687a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                        new Account(accountName, accountType),
13697a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                        authorityName, -1, false);
1370231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
1371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int i = mSyncStatus.size();
1372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean found = false;
1373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo st = null;
1374231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (i > 0) {
1375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        i--;
1376360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                        st = mSyncStatus.valueAt(i);
1377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (st.authorityId == authority.ident) {
1378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            found = true;
1379231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
1380231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!found) {
1383231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        st = new SyncStatusInfo(authority.ident);
1384231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(authority.ident, st);
1385231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.totalElapsedTime = getLongColumn(c, "totalElapsedTime");
1387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSyncs = getIntColumn(c, "numSyncs");
1388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceLocal = getIntColumn(c, "numSourceLocal");
1389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourcePoll = getIntColumn(c, "numSourcePoll");
1390231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceServer = getIntColumn(c, "numSourceServer");
1391231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceUser = getIntColumn(c, "numSourceUser");
1392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessSource = getIntColumn(c, "lastSuccessSource");
1393231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessTime = getLongColumn(c, "lastSuccessTime");
1394231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureSource = getIntColumn(c, "lastFailureSource");
1395231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureTime = getLongColumn(c, "lastFailureTime");
1396231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureMesg = c.getString(c.getColumnIndex("lastFailureMesg"));
1397231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.pending = getIntColumn(c, "pending") != 0;
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1400360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1401231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c.close();
1402360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1403231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Retrieve the settings.
1404231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb = new SQLiteQueryBuilder();
1405231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("settings");
1406231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c = qb.query(db, null, null, null, null, null, null);
1407231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (c.moveToNext()) {
1408231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String name = c.getString(c.getColumnIndex("name"));
1409231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String value = c.getString(c.getColumnIndex("value"));
1410231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name == null) continue;
1411231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name.equals("listen_for_tickles")) {
1412ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    setMasterSyncAutomatically(value == null || Boolean.parseBoolean(value));
1413231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else if (name.startsWith("sync_provider_")) {
1414231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    String provider = name.substring("sync_provider_".length(),
1415231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            name.length());
1416ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    int i = mAuthorities.size();
1417ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    while (i > 0) {
1418ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        i--;
1419360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                        AuthorityInfo authority = mAuthorities.valueAt(i);
1420ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        if (authority.authority.equals(provider)) {
1421ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                            authority.enabled = value == null || Boolean.parseBoolean(value);
14225e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                            authority.syncable = 1;
1423ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        }
1424ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    }
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1427360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.close();
1429360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1430231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db.close();
1431360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1432231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
1433231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeStatusLocked();
1434231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            (new File(path)).delete();
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1437360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1438231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_END = 0;
1439231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_ITEM = 100;
1440360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1441231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1442231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync status back in to the initial engine state.
1443231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1444231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatusLocked() {
1445231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Reading " + mStatusFile.getBaseFile());
1446231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1447231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatusFile.readFully();
1448231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1449231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1450231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1451231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
1452231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATUS_FILE_END) {
1453231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATUS_FILE_ITEM) {
1454231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo status = new SyncStatusInfo(in);
1455231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.indexOfKey(status.authorityId) >= 0) {
1456231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
1457231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (DEBUG_FILE) Log.v(TAG, "Adding status for id "
1458231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                + status.authorityId);
1459231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(status.authorityId, status);
1460231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1461231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
1462231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
1463231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown status token: " + token);
1464231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1465231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1466231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1467231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1468231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial status");
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1471360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1472231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1473231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync status to the sync status file.
1474231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1475231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatusLocked() {
1476231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatusFile.getBaseFile());
1477360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1478231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
1479231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
1480231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATUS);
1481360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1482231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1484231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatusFile.startWrite();
1485231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1486231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1487231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1488231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo status = mSyncStatus.valueAt(i);
1489231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATUS_FILE_ITEM);
1490231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.writeToParcel(out, 0);
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1492231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATUS_FILE_END);
1493231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1494231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1495360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1496231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatusFile.finishWrite(fos);
1497231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1498231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing status", e1);
1499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1500231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatusFile.failWrite(fos);
1501231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1502231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1503231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1504360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1505307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public static final int PENDING_OPERATION_VERSION = 2;
1506360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1507231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1508231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all pending operations back in to the initial engine state.
1509231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1510231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readPendingOperationsLocked() {
1511231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Reading " + mPendingFile.getBaseFile());
1512231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1513231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mPendingFile.readFully();
1514231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1515231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1516231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1517231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int SIZE = in.dataSize();
1518231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (in.dataPosition() < SIZE) {
1519231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int version = in.readInt();
1520307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                if (version != PENDING_OPERATION_VERSION && version != 1) {
1521231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown pending operation version "
1522231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + version + "; dropping all ops");
1523231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1524231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1525231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int authorityId = in.readInt();
1526231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int syncSource = in.readInt();
1527231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                byte[] flatExtras = in.createByteArray();
1528307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                boolean expedited;
1529307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                if (version == PENDING_OPERATION_VERSION) {
1530307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    expedited = in.readInt() != 0;
1531307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                } else {
1532307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    expedited = false;
1533307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                }
1534231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(authorityId);
1535231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
1536231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Bundle extras = null;
1537231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (flatExtras != null) {
1538231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        extras = unflattenBundle(flatExtras);
1539231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1540231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    PendingOperation op = new PendingOperation(
1541231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            authority.account, syncSource,
1542307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            authority.authority, extras, expedited);
1543231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.authorityId = authorityId;
1544231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.flatExtras = flatExtras;
1545231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + op.account
1546231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " auth=" + op.authority
1547231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " src=" + op.syncSource
1548307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                            + " expedited=" + op.expedited
1549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " extras=" + op.extras);
1550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mPendingOperations.add(op);
1551231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1552231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1553231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1554231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial pending operations");
1555231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1556231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1557360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1558231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writePendingOperationLocked(PendingOperation op, Parcel out) {
1559231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(PENDING_OPERATION_VERSION);
1560231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(op.authorityId);
1561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(op.syncSource);
1562231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (op.flatExtras == null && op.extras != null) {
1563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op.flatExtras = flattenBundle(op.extras);
1564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeByteArray(op.flatExtras);
1566307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        out.writeInt(op.expedited ? 1 : 0);
1567231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1568360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1569231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1570231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all currently pending ops to the pending ops file.
1571231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1572231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writePendingOperationsLocked() {
1573231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int N = mPendingOperations.size();
1574231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1575231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1576231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (N == 0) {
1577231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG_FILE) Log.v(TAG, "Truncating " + mPendingFile.getBaseFile());
1578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mPendingFile.truncate();
1579231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
1580231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1581360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1582231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Writing new " + mPendingFile.getBaseFile());
1583231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mPendingFile.startWrite();
1584360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1585231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1586231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1587231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                PendingOperation op = mPendingOperations.get(i);
1588231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationLocked(op, out);
1589231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1590231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1591231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1592360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1593231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingFile.finishWrite(fos);
1594231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1595231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing pending operations", e1);
1596231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1597231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mPendingFile.failWrite(fos);
1598231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1599231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1600231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1601360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1602231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1603231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Append the given operation to the pending ops file; if unable to,
1604231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * write all pending ops.
1605231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1606231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void appendPendingOperationLocked(PendingOperation op) {
1607231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
1608231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1609231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1610231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mPendingFile.openAppend();
1611231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1612231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Failed append; writing full file");
1613231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationsLocked();
1614231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
1615231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1616360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1617231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1618231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1619231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationLocked(op, out);
1620231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1621231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1622231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1623231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing pending operations", e1);
1624231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1625231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            try {
1626231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                fos.close();
1627231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } catch (java.io.IOException e2) {
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1629231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1630231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1631360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1632231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static private byte[] flattenBundle(Bundle bundle) {
1633231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        byte[] flatData = null;
1634231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Parcel parcel = Parcel.obtain();
1635231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1636231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle.writeToParcel(parcel, 0);
1637231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            flatData = parcel.marshall();
1638231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1639231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.recycle();
1640231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1641231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return flatData;
1642231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1643360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1644231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static private Bundle unflattenBundle(byte[] flatData) {
1645231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Bundle bundle;
1646231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Parcel parcel = Parcel.obtain();
1647231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1648231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.unmarshall(flatData, 0, flatData.length);
1649231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.setDataPosition(0);
1650231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle = parcel.readBundle();
1651231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (RuntimeException e) {
1652231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // A RuntimeException is thrown if we were unable to parse the parcel.
1653231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Create an empty parcel in this case.
1654231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle = new Bundle();
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
1656231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.recycle();
1657231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1658231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return bundle;
1659231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1660360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1661231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_END = 0;
1662231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM_OLD = 100;
1663231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM = 101;
1664360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1665231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1666231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync statistics back in to the initial engine state.
1667231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1668231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatisticsLocked() {
1669231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1670231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatisticsFile.readFully();
1671231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1672231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1673231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1674231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
1675231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int index = 0;
1676231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATISTICS_FILE_END) {
1677231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATISTICS_FILE_ITEM
1678231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || token == STATISTICS_FILE_ITEM_OLD) {
1679231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int day = in.readInt();
1680231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (token == STATISTICS_FILE_ITEM_OLD) {
1681231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        day = day - 2009 + 14245;  // Magic!
1682231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1683231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    DayStats ds = new DayStats(day);
1684231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successCount = in.readInt();
1685231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successTime = in.readLong();
1686231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureCount = in.readInt();
1687231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureTime = in.readLong();
1688231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (index < mDayStats.length) {
1689231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mDayStats[index] = ds;
1690231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        index++;
1691231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1692231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
1693231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
1694231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown stats token: " + token);
1695231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1696231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1697231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1698231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1699231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial statistics");
1700231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1701231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1702360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1703231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1704231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync statistics to the sync status file.
1705231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1706231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatisticsLocked() {
1707231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
1708360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1709231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
1710231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
1711231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATISTICS);
1712360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1713231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1714231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1715231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatisticsFile.startWrite();
1716231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1717231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mDayStats.length;
1718231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1719231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                DayStats ds = mDayStats[i];
1720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ds == null) {
1721231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1723231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATISTICS_FILE_ITEM);
1724231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.day);
1725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.successCount);
1726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.successTime);
1727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.failureCount);
1728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.failureTime);
1729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1730231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATISTICS_FILE_END);
1731231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1732231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1733360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1734231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatisticsFile.finishWrite(fos);
1735231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1736231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing stats", e1);
1737231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1738231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatisticsFile.failWrite(fos);
1739231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1743