SyncStorageEngine.java revision ac9385ef3105fb7464e1f46049c62755a8b7f0e9
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;
21231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport com.android.internal.util.FastXmlSerializer;
22231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
23231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport org.xmlpull.v1.XmlPullParser;
24231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
25231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport org.xmlpull.v1.XmlSerializer;
26231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
27d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintanaimport android.accounts.Account;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
30231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.database.sqlite.SQLiteException;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder;
32231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Bundle;
33231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Environment;
34231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Handler;
35231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Message;
36231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel;
37231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteCallbackList;
38231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteException;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
40231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.SparseArray;
41231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.Xml;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
43231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.File;
44231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileInputStream;
45231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileOutputStream;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
47231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Calendar;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
49231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Iterator;
50231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.TimeZone;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
53231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Singleton that tracks the sync data and overall sync
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * history on the device.
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
58231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornpublic class SyncStorageEngine extends Handler {
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SyncManager";
60231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final boolean DEBUG = false;
61231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final boolean DEBUG_FILE = false;
62231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
63231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // @VisibleForTesting
64231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
66231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync start event. */
67231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_START = 0;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
69231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync stop event. */
70231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_STOP = 1;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
72231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
73231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync event types. */
74231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] EVENTS = { "START", "STOP" };
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
76231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a server-initiated sync. */
77231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_SERVER = 0;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
79231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a local-initiated sync. */
80231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_LOCAL = 1;
81231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
82231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Enum value for a poll-based sync (e.g., upon connection to
83231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * network)
84231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
85231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_POLL = 2;
86231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
87231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a user-initiated sync. */
88231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_USER = 3;
89231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
90ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    private static final Intent SYNC_CONNECTION_SETTING_CHANGED_INTENT =
91ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
92ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
93231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
94231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync source types. */
95231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] SOURCES = { "SERVER",
96231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "LOCAL",
97231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "POLL",
98231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "USER" };
99231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
100231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // The MESG column will contain one of these or one of the Error types.
101231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_SUCCESS = "success";
102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_CANCELED = "canceled";
103231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int MAX_HISTORY = 15;
105231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
106231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATUS = 1;
107231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATUS_DELAY = 1000*60*10; // 10 minutes
108231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
109231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATISTICS = 2;
110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATISTICS_DELAY = 1000*60*30; // 1/2 hour
111231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
112231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class PendingOperation {
1137a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int syncSource;
115231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String authority;
116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final Bundle extras;        // note: read-only.
117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int authorityId;
119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        byte[] flatExtras;
120231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1217a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        PendingOperation(Account account, int source,
122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String authority, Bundle extras) {
123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = source;
125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = authority;
126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = extras != null ? new Bundle(extras) : extras;
127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authorityId = -1;
128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        PendingOperation(PendingOperation other) {
131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = other.account;
132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = other.syncSource;
133231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = other.authority;
134231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = other.extras;
135231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authorityId = other.authorityId;
136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static class AccountInfo {
1407a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final HashMap<String, AuthorityInfo> authorities =
142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                new HashMap<String, AuthorityInfo>();
143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1447a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        AccountInfo(Account account) {
145231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
147231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
149231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class AuthorityInfo {
1507a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
151231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String authority;
152231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int ident;
153231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean enabled;
154ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
1557a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        AuthorityInfo(Account account, String authority, int ident) {
156231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
157231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = authority;
158231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.ident = ident;
159231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            enabled = true;
160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
162231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
163231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class SyncHistoryItem {
164231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int authorityId;
165231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int historyId;
166231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long eventTime;
167231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long elapsedTime;
168231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int source;
169231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int event;
170231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long upstreamActivity;
171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long downstreamActivity;
172231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String mesg;
173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
174231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
175231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class DayStats {
176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public final int day;
177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int successCount;
178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long successTime;
179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int failureCount;
180231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long failureTime;
181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
182231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public DayStats(int day) {
183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.day = day;
184231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // Primary list of all syncable authorities.  Also our global lock.
188231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<AuthorityInfo> mAuthorities =
189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<AuthorityInfo>();
190231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1917a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private final HashMap<Account, AccountInfo> mAccounts =
1927a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        new HashMap<Account, AccountInfo>();
193231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
194231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<PendingOperation> mPendingOperations =
195231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<PendingOperation>();
196231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
197231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private ActiveSyncInfo mActiveSync;
198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
199231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<SyncStatusInfo> mSyncStatus =
200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<SyncStatusInfo>();
201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<SyncHistoryItem> mSyncHistory =
203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<SyncHistoryItem>();
204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final RemoteCallbackList<ISyncStatusObserver> mChangeListeners
206231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            = new RemoteCallbackList<ISyncStatusObserver>();
207231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // We keep 4 weeks of stats.
209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final DayStats[] mDayStats = new DayStats[7*4];
210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Calendar mCal;
211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYear;
212231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYearInDays;
213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
214231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Context mContext;
215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static volatile SyncStorageEngine sSyncStorageEngine = null;
216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
217231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
218231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the core engine state: all accounts and the
219231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * settings for them.  It must never be lost, and should be changed
220231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * infrequently, so it is stored as an XML file.
221231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
222231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mAccountInfoFile;
223231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
224231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the current sync status.  We would like to retain
226231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * it across boots, but its loss is not the end of the world, so we store
227231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * this information as binary data.
228231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
229231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatusFile;
230231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
231231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
232231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains sync statistics.  This is purely debugging information
233231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so is written infrequently and can be thrown away at any time.
234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
235231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatisticsFile;
236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
238231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the pending sync operations.  It is a binary file,
239231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * which must be updated every time an operation is added or removed,
240231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so we have special handling of it.
241231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mPendingFile;
243231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int PENDING_FINISH_TO_WRITE = 4;
244231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNumPendingFinished = 0;
245231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
246231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNextHistoryId = 0;
247ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    private boolean mMasterSyncAutomatically = true;
248231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SyncStorageEngine(Context context) {
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sSyncStorageEngine = this;
252231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
253231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
254231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
255231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File dataDir = Environment.getDataDirectory();
256231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File systemDir = new File(dataDir, "system");
257231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File syncDir = new File(systemDir, "sync");
258231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
259231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
260231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mPendingFile = new AtomicFile(new File(syncDir, "pending.bin"));
261231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
262231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
263231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readAccountInfoLocked();
264231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatusLocked();
265231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readPendingOperationsLocked();
266231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatisticsLocked();
267231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readLegacyAccountInfoLocked();
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine newTestInstance(Context context) {
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new SyncStorageEngine(context);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void init(Context context) {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine != null) {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("already initialized");
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sSyncStorageEngine = new SyncStorageEngine(context);
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine getSingleton() {
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine == null) {
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("not initialized");
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sSyncStorageEngine;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
288231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    @Override public void handleMessage(Message msg) {
289231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (msg.what == MSG_WRITE_STATUS) {
290231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            synchronized (mAccounts) {
291231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
292231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
293231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } else if (msg.what == MSG_WRITE_STATISTICS) {
294231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            synchronized (mAccounts) {
295231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
298231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
299231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
300231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
301231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
302231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.register(callback, mask);
303231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
304231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
305231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
306231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void removeStatusChangeListener(ISyncStatusObserver callback) {
307231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
308231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.unregister(callback);
309231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
310231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
311231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
312231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void reportChange(int which) {
313231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        ArrayList<ISyncStatusObserver> reports = null;
314231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
315231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mChangeListeners.beginBroadcast();
316231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
317231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
318231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Integer mask = (Integer)mChangeListeners.getBroadcastCookie(i);
319231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if ((which & mask.intValue()) == 0) {
320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
321231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (reports == null) {
323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports = new ArrayList<ISyncStatusObserver>(i);
324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
325231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                reports.add(mChangeListeners.getBroadcastItem(i));
326231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
329231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG) Log.v(TAG, "reportChange " + which + " to: " + reports);
330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
331231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (reports != null) {
332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = reports.size();
333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
336231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports.get(i).onStatusChanged(which);
337231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (RemoteException e) {
338231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // The remote callback list will take care of this for us.
339231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
340231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
341231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
342231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
343231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
344ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getSyncAutomatically(Account account, String providerName) {
345231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
346231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (account != null) {
347231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(account, providerName,
348ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        "getSyncAutomatically");
349ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return authority != null && authority.enabled;
350231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
351ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
352231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mAuthorities.size();
353231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
354231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
355231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(i);
356231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority.authority.equals(providerName)
357231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        && authority.enabled) {
358231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
365ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setSyncAutomatically(Account account, String providerName, boolean sync) {
366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
367ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            AuthorityInfo authority = getAuthorityLocked(account, providerName,
368ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    "setSyncAutomatically");
369ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (authority != null) {
370ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                authority.enabled = sync;
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
374231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
375ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
378ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public void setMasterSyncAutomatically(boolean flag) {
379231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
380ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            mMasterSyncAutomatically = flag;
381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
383ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
384ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        mContext.sendBroadcast(SYNC_CONNECTION_SETTING_CHANGED_INTENT);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
387ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean getMasterSyncAutomatically() {
388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
389ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            return mMasterSyncAutomatically;
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
3937a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public AuthorityInfo getAuthority(Account account, String authority) {
394231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
395231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return getAuthorityLocked(account, authority, null);
396231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
398231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
399231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public AuthorityInfo getAuthority(int authorityId) {
400231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
401231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mAuthorities.get(authorityId);
402231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
403231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
404231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
406231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Returns true if there is currently a sync operation for the given
407231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * account or authority in the pending list, or actively being processed.
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4097a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public boolean isSyncActive(Account account, String authority) {
410231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
411231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mPendingOperations.size();
412231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
413231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
414231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // TODO(fredq): this probably shouldn't be considering
415231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // pending operations.
416231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                PendingOperation op = mPendingOperations.get(i);
417231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (op.account.equals(account) && op.authority.equals(authority)) {
418231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
419231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
420231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
421231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
422231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mActiveSync != null) {
423231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = getAuthority(mActiveSync.authorityId);
424231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo != null && ainfo.account.equals(account)
425231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        && ainfo.authority.equals(authority)) {
426231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
427231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
428231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
430231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
431231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
432231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
433231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
434231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public PendingOperation insertIntoPending(PendingOperation op) {
435231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
436231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertIntoPending: account=" + op.account
437231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
438231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
439231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
440231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
441231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getOrCreateAuthorityLocked(op.account,
442231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.authority,
443231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    -1 /* desired identifier */,
444231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    true /* write accounts to storage */);
445231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
446231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return null;
447231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
448231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
449231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op = new PendingOperation(op);
450231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op.authorityId = authority.ident;
451231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.add(op);
452231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            appendPendingOperationLocked(op);
453231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
454231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
455231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.pending = true;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
457231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
458ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
459231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return op;
460231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
462231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean deleteFromPending(PendingOperation op) {
463231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean res = false;
464231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
465231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "deleteFromPending: account=" + op.account
466231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
467231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
468231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
469231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mPendingOperations.remove(op)) {
470231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mPendingOperations.size() == 0
471231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || mNumPendingFinished >= PENDING_FINISH_TO_WRITE) {
472231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writePendingOperationsLocked();
473231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished = 0;
474231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
475231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished++;
476231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
477231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
478231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(op.account, op.authority,
479231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "deleteFromPending");
480231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
481231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.v(TAG, "removing - " + authority);
482231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    final int N = mPendingOperations.size();
483231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean morePending = false;
484231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (int i=0; i<N; i++) {
485231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        PendingOperation cur = mPendingOperations.get(i);
486231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (cur.account.equals(op.account)
487231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                && cur.authority.equals(op.authority)) {
488231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            morePending = true;
489231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
490231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
491231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
492231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
493231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!morePending) {
494231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (DEBUG) Log.v(TAG, "no more pending!");
495231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
496231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
497231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
498231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
500231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                res = true;
501231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
502231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
503231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
504ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
505231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return res;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
508231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int clearPending() {
509231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int num;
510231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
511231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "clearPending");
512231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            num = mPendingOperations.size();
513231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.clear();
514231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
515231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
516231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mSyncStatus.get(i).pending = false;
517231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
518231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationsLocked();
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
520ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
521231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return num;
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
525231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return a copy of the current array of pending operations.  The
526231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * PendingOperation objects are the real objects stored inside, so that
527231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * they can be used with deleteFromPending().
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
529231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<PendingOperation> getPendingOperations() {
530231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
531231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return new ArrayList<PendingOperation>(mPendingOperations);
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
534231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
536231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the number of currently pending operations.
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
538231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int getPendingOperationCount() {
539231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
540231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mPendingOperations.size();
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
543231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
545231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the set of account has changed, given the new array of
546231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active accounts.
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5487a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public void doDatabaseCleanup(Account[] accounts) {
549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.w(TAG, "Updating for new accounts...");
551231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SparseArray<AuthorityInfo> removing = new SparseArray<AuthorityInfo>();
552231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Iterator<AccountInfo> accIt = mAccounts.values().iterator();
553231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (accIt.hasNext()) {
554231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AccountInfo acc = accIt.next();
555231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!ArrayUtils.contains(accounts, acc.account)) {
556231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // This account no longer exists...
557231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.w(TAG, "Account removed: " + acc.account);
558231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (AuthorityInfo auth : acc.authorities.values()) {
559231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        removing.put(auth.ident, auth);
560231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    accIt.remove();
562231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Clean out all data structures.
566231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = removing.size();
567231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (i > 0) {
568231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                while (i > 0) {
569231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    i--;
570231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int ident = removing.keyAt(i);
571231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mAuthorities.remove(ident);
572231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int j = mSyncStatus.size();
573231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
574231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
575231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncStatus.keyAt(j) == ident) {
576231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncStatus.remove(mSyncStatus.keyAt(j));
577231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
579231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    j = mSyncHistory.size();
580231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
581231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
582231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncHistory.get(j).authorityId == ident) {
583231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncHistory.remove(j);
584231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
585231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
586231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
587231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
588231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
589231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationsLocked();
590231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
591231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
595231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
596231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the currently active sync is changing (there can only be
597231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * one at a time).  Either supply a valid ActiveSyncContext with information
598231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * about the sync, or null to stop the currently active sync.
599231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
600231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void setActiveSync(SyncManager.ActiveSyncContext activeSyncContext) {
601231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
602231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (activeSyncContext != null) {
603231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: account="
604231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + activeSyncContext.mSyncOperation.account
605231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " auth=" + activeSyncContext.mSyncOperation.authority
606231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " src=" + activeSyncContext.mSyncOperation.syncSource
607231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " extras=" + activeSyncContext.mSyncOperation.extras);
608231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mActiveSync != null) {
609231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "setActiveSync called with existing active sync!");
610231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
611231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(
612231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.account,
613231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.authority,
614231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "setActiveSync");
615231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority == null) {
616231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return;
617231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
618231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = new ActiveSyncInfo(authority.ident,
619231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        authority.account, authority.authority,
620231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mStartTime);
621231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else {
622231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: null");
623231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = null;
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
626231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
627ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
630231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
631231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * To allow others to send active change reports, to poke clients.
632231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
633231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void reportActiveChange() {
634ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
635231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
636231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
637231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
638231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Note that sync has started for the given account and authority.
639231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
6407a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    public long insertStartSyncEvent(Account accountName, String authorityName,
641231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long now, int source) {
642231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long id;
643231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
644231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertStartSyncEvent: account=" + accountName
645231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + authorityName + " source=" + source);
646231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getAuthorityLocked(accountName, authorityName,
647231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    "insertStartSyncEvent");
648231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
649231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return -1;
650231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
651231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = new SyncHistoryItem();
652231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.authorityId = authority.ident;
653231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.historyId = mNextHistoryId++;
654231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mNextHistoryId < 0) mNextHistoryId = 0;
655231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.eventTime = now;
656231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.source = source;
657231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_START;
658231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncHistory.add(0, item);
659231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (mSyncHistory.size() > MAX_HISTORY) {
660231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mSyncHistory.remove(mSyncHistory.size()-1);
661231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
662231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            id = item.historyId;
663231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "returning historyId " + id);
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
665231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
666ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
667231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return id;
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
670231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
671231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long downstreamActivity, long upstreamActivity) {
672231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
673231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "stopSyncEvent: historyId=" + historyId);
674231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = null;
675231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncHistory.size();
676231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
677231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
678231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = mSyncHistory.get(i);
679231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (item.historyId == historyId) {
680231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
681231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
682231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = null;
683231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
684231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
685231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (item == null) {
686231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, "stopSyncEvent: no history for id " + historyId);
687231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
688231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
689231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
690231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.elapsedTime = elapsedTime;
691231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_STOP;
692231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.mesg = resultMessage;
693231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.downstreamActivity = downstreamActivity;
694231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.upstreamActivity = upstreamActivity;
695231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
696231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(item.authorityId);
697231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
698231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.numSyncs++;
699231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.totalElapsedTime += elapsedTime;
700231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            switch (item.source) {
701231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_LOCAL:
702231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceLocal++;
703231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
704231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_POLL:
705231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourcePoll++;
706231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
707231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_USER:
708231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceUser++;
709231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
710231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_SERVER:
711231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceServer++;
712231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
713231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
714231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
715231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatisticsNow = false;
71655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            int day = getCurrentDayLocked();
717231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mDayStats[0] == null) {
718231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
719231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (day != mDayStats[0].day) {
720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                System.arraycopy(mDayStats, 0, mDayStats, 1, mDayStats.length-1);
721231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsNow = true;
723231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (mDayStats[0] == null) {
724231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final DayStats ds = mDayStats[0];
726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final long lastSyncTime = (item.eventTime + elapsedTime);
728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatusNow = false;
729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (MESG_SUCCESS.equals(resultMessage)) {
730231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // - if successful, update the successful columns
731231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastSuccessTime == 0 || status.lastFailureTime != 0) {
732231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
733231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
734231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessTime = lastSyncTime;
735231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessSource = item.source;
736231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = 0;
737231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = -1;
738231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = null;
739231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.initialFailureTime = 0;
740231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successCount++;
741231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successTime += elapsedTime;
742231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!MESG_CANCELED.equals(resultMessage)) {
743231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastFailureTime == 0) {
744231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
745231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
746231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = lastSyncTime;
747231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = item.source;
748231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = resultMessage;
749231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.initialFailureTime == 0) {
750231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.initialFailureTime = lastSyncTime;
751231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
752231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureCount++;
753231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureTime += elapsedTime;
754231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
755231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
756231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatusNow) {
757231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
758231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATUS)) {
759231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATUS),
760231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATUS_DELAY);
761231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
762231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatisticsNow) {
763231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
764231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATISTICS)) {
765231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATISTICS),
766231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATISTICS_DELAY);
767231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
769231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
770ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
774231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the currently active sync information, or null if there is no
775231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active sync.  Note that the returned object is the real, live active
776231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync object, so be careful what you do with it.
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
778231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ActiveSyncInfo getActiveSync() {
779231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
780231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mActiveSync;
781231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
783231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
784231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
785231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
786231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
787231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
788231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
789231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncStatusInfo> getSyncStatus() {
790231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
791231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
792231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncStatusInfo> ops = new ArrayList<SyncStatusInfo>(N);
793231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
794231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ops.add(mSyncStatus.valueAt(i));
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
796231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ops;
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
799231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
800231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
801231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Returns the status that matches the authority. If there are multiples accounts for
802231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * the authority, the one with the latest "lastSuccessTime" status is returned.
803231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authority the authority whose row should be selected
804231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @return the SyncStatusInfo for the authority, or null if none exists
805231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
806231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public SyncStatusInfo getStatusByAuthority(String authority) {
807231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
808231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo best = null;
809231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
810231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
811231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo cur = mSyncStatus.get(i);
812231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
813231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo != null && ainfo.authority.equals(authority)) {
814231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (best == null) {
815231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        best = cur;
816231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    } else if (best.lastSuccessTime > cur.lastSuccessTime) {
817231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        best = cur;
818231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
819231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
820231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
821231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return best;
822231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
824231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
825231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
826231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return true if the pending status is true of any matching authorities.
827231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
828ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana    public boolean isSyncPending(Account account, String authority) {
829231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
830231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
831231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
832231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo cur = mSyncStatus.get(i);
833231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
834231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo == null) {
835231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
836231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
837231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (account != null && !ainfo.account.equals(account)) {
838231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
839231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
840231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo.authority.equals(authority) && cur.pending) {
841231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
844231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
849231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
850231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
851231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
852231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
853231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncHistoryItem> getSyncHistory() {
854231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
855231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncHistory.size();
856231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncHistoryItem> items = new ArrayList<SyncHistoryItem>(N);
857231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
858231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                items.add(mSyncHistory.get(i));
859231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
860231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return items;
861231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
862231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
863231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
864231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
865231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current per-day statistics.  Note
866231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
867231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
868231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
869231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public DayStats[] getDayStatistics() {
870231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
871231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            DayStats[] ds = new DayStats[mDayStats.length];
872231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            System.arraycopy(mDayStats, 0, ds, 0, ds.length);
873231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ds;
874231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
875231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
876231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
877231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If sync is failing for any of the provider/accounts then determine the time at which it
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * started failing and return the earliest time over all the provider/accounts. If none are
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * failing then return 0.
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getInitialSyncFailureTime() {
883231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
884ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (!mMasterSyncAutomatically) {
885231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return 0;
886231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
887231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
888231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long oldest = 0;
889231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncStatus.size();
890231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
891231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
892231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo stats = mSyncStatus.valueAt(i);
893231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(stats.authorityId);
894231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null && authority.enabled) {
895231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (oldest == 0 || stats.initialFailureTime < oldest) {
896231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        oldest = stats.initialFailureTime;
897231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
898231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
899231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
900231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
901231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return oldest;
902231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
903231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
904231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
90555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private int getCurrentDayLocked() {
906231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal.setTimeInMillis(System.currentTimeMillis());
907231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
908231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (mYear != mCal.get(Calendar.YEAR)) {
909231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYear = mCal.get(Calendar.YEAR);
910231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.clear();
911231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.set(Calendar.YEAR, mYear);
912231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYearInDays = (int)(mCal.getTimeInMillis()/86400000);
913231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
914231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return dayOfYear + mYearInDays;
915231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
916231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
917231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
918231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Retrieve an authority, returning null if one does not exist.
919231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     *
920231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param accountName The name of the account for the authority.
921231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authorityName The name of the authority itself.
922231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param tag If non-null, this will be used in a log message if the
923231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * requested authority does not exist.
924231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
9257a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private AuthorityInfo getAuthorityLocked(Account accountName, String authorityName,
926231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tag) {
927231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
928231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
929231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
930231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, tag + ": unknown account " + accountName);
931231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
932231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
933231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
934231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
935231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
936231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
937231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, tag + ": unknown authority " + authorityName);
938231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
939231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
940231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
941231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
942231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
943231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
944231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
9457a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn    private AuthorityInfo getOrCreateAuthorityLocked(Account accountName,
946231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String authorityName, int ident, boolean doWrite) {
947231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
948231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
949231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account = new AccountInfo(accountName);
950231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccounts.put(accountName, account);
951231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
952231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
953231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
954231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (ident < 0) {
955231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // Look for a new identifier for this authority.
956231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                final int N = mAuthorities.size();
957231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ident = 0;
958231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                for (int i=0; i<N; i++) {
959231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.valueAt(i).ident > ident) {
960231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        break;
961231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
962231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ident++;
963231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
964231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
965231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            authority = new AuthorityInfo(accountName, authorityName, ident);
966231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account.authorities.put(authorityName, authority);
967231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAuthorities.put(ident, authority);
968231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (doWrite) {
969231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
970231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
971231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
972231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
973231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
974231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
975231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
976231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private SyncStatusInfo getOrCreateSyncStatusLocked(int authorityId) {
977231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SyncStatusInfo status = mSyncStatus.get(authorityId);
978231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (status == null) {
979231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status = new SyncStatusInfo(authorityId);
980231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncStatus.put(authorityId, status);
981231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
982231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return status;
983231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
984231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
98555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    public void writeAllState() {
98655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        synchronized (mAuthorities) {
98755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Account info is always written so no need to do it here.
98855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
98955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            if (mNumPendingFinished > 0) {
99055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                // Only write these if they are out of date.
99155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                writePendingOperationsLocked();
99255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
99355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
99455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Just always write these...  they are likely out of date.
99555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatusLocked();
99655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatisticsLocked();
99755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
99855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
99955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
1000231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1001231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all account information back in to the initial engine state.
1002231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1003231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readAccountInfoLocked() {
1004231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileInputStream fis = null;
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1006231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fis = mAccountInfoFile.openRead();
1007231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading " + mAccountInfoFile.getBaseFile());
1008231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlPullParser parser = Xml.newPullParser();
1009231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parser.setInput(fis, null);
1010231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int eventType = parser.getEventType();
1011231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (eventType != XmlPullParser.START_TAG) {
1012231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1013231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1014231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tagName = parser.getName();
1015231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if ("accounts".equals(tagName)) {
1016231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String listen = parser.getAttributeValue(
1017231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        null, "listen-for-tickles");
1018ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                mMasterSyncAutomatically = listen == null
1019231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            || Boolean.parseBoolean(listen);
1020231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1021231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                do {
1022231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (eventType == XmlPullParser.START_TAG
1023231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            && parser.getDepth() == 2) {
1024231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        tagName = parser.getName();
1025231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if ("authority".equals(tagName)) {
1026231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            int id = -1;
1027231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            try {
1028231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                id = Integer.parseInt(parser.getAttributeValue(
1029231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "id"));
1030231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            } catch (NumberFormatException e) {
1031231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            } catch (NullPointerException e) {
1032231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1033231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            if (id >= 0) {
1034231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                String accountName = parser.getAttributeValue(
1035231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "account");
10367a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                String accountType = parser.getAttributeValue(
10377a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                        null, "type");
10387a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                if (accountType == null) {
10397a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                    accountType = "com.google.GAIA";
10407a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                }
1041231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                String authorityName = parser.getAttributeValue(
1042231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "authority");
1043231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                String enabled = parser.getAttributeValue(
1044231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "enabled");
1045231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                AuthorityInfo authority = mAuthorities.get(id);
1046231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                if (DEBUG_FILE) Log.v(TAG, "Adding authority: account="
1047231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        + accountName + " auth=" + authorityName
1048231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        + " enabled=" + enabled);
1049231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                if (authority == null) {
1050231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    if (DEBUG_FILE) Log.v(TAG, "Creating entry");
1051231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    authority = getOrCreateAuthorityLocked(
10527a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                            new Account(accountName, accountType),
10537a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                                            authorityName, id, false);
1054231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                }
1055231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                if (authority != null) {
1056231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    authority.enabled = enabled == null
1057231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                            || Boolean.parseBoolean(enabled);
1058231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                } else {
1059231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    Log.w(TAG, "Failure adding authority: account="
1060231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                            + accountName + " auth=" + authorityName
1061231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                            + " enabled=" + enabled);
1062231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                }
1063231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1064231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1065231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1066231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    eventType = parser.next();
1067231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } while (eventType != XmlPullParser.END_DOCUMENT);
1068231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1069231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (XmlPullParserException e) {
1070231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error reading accounts", e);
1071231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1072231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis == null) Log.i(TAG, "No initial accounts");
1073231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            else Log.w(TAG, "Error reading accounts", e);
1074231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1075231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis != null) {
1076231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
1077231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    fis.close();
1078231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (java.io.IOException e1) {
1079231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1080231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1081231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1082231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1083231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1084231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1085231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all account information to the account file.
1086231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1087231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeAccountInfoLocked() {
1088231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
1089231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1090231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1091231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1092231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mAccountInfoFile.startWrite();
1093231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlSerializer out = new FastXmlSerializer();
1094231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setOutput(fos, "utf-8");
1095231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startDocument(null, true);
1096231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1097231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1098231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startTag(null, "accounts");
1099ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana            if (!mMasterSyncAutomatically) {
1100231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "listen-for-tickles", "false");
1101231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1103231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mAuthorities.size();
1104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1105231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(i);
1106231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.startTag(null, "authority");
1107231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "id", Integer.toString(authority.ident));
11087a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                out.attribute(null, "account", authority.account.mName);
11097a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                out.attribute(null, "type", authority.account.mType);
1110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "authority", authority.authority);
1111231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!authority.enabled) {
1112231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    out.attribute(null, "enabled", "false");
1113231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.endTag(null, "authority");
1115231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endTag(null, "accounts");
1118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endDocument();
1120231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1121231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccountInfoFile.finishWrite(fos);
1122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing accounts", e1);
1124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mAccountInfoFile.failWrite(fos);
1126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static int getIntColumn(Cursor c, String name) {
1131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getInt(c.getColumnIndex(name));
1132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1133231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1134231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static long getLongColumn(Cursor c, String name) {
1135231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getLong(c.getColumnIndex(name));
1136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Load sync engine state from the old syncmanager database, and then
1140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * erase it.  Note that we don't deal with pending operations, active
1141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync, or history.
1142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readLegacyAccountInfoLocked() {
1144231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // Look for old database to initialize from.
1145231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File file = mContext.getDatabasePath("syncmanager.db");
1146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (!file.exists()) {
1147231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
1148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1149231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String path = file.getPath();
1150231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SQLiteDatabase db = null;
1151231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1152231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db = SQLiteDatabase.openDatabase(path, null,
1153231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SQLiteDatabase.OPEN_READONLY);
1154231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (SQLiteException e) {
1155231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1156231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1157231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (db != null) {
11582d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            final boolean hasType = db.getVersion() >= 11;
11592d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn
1160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Copy in all of the status information, as well as accounts.
1161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading legacy sync accounts db");
1162231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
1163231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("stats, status");
1164231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            HashMap<String,String> map = new HashMap<String,String>();
1165231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("_id", "status._id as _id");
1166231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("account", "stats.account as account");
11672d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            if (hasType) {
11682d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                map.put("account_type", "stats.account_type as account_type");
11692d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            }
1170231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("authority", "stats.authority as authority");
1171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("totalElapsedTime", "totalElapsedTime");
1172231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSyncs", "numSyncs");
1173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceLocal", "numSourceLocal");
1174231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourcePoll", "numSourcePoll");
1175231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceServer", "numSourceServer");
1176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceUser", "numSourceUser");
1177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessSource", "lastSuccessSource");
1178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessTime", "lastSuccessTime");
1179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureSource", "lastFailureSource");
1180231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureTime", "lastFailureTime");
1181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureMesg", "lastFailureMesg");
1182231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("pending", "pending");
1183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setProjectionMap(map);
1184231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.appendWhere("stats._id = status.stats_id");
1185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Cursor c = qb.query(db, null, null, null, null, null, null);
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (c.moveToNext()) {
1187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String accountName = c.getString(c.getColumnIndex("account"));
11882d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                String accountType = hasType
11892d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                        ? c.getString(c.getColumnIndex("account_type")) : null;
11907a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                if (accountType == null) {
11917a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                    accountType = "com.google.GAIA";
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1193231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String authorityName = c.getString(c.getColumnIndex("authority"));
1194231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = this.getOrCreateAuthorityLocked(
11957a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                        new Account(accountName, accountType),
11967a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                        authorityName, -1, false);
1197231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
1198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int i = mSyncStatus.size();
1199231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean found = false;
1200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo st = null;
1201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (i > 0) {
1202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        i--;
1203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        st = mSyncStatus.get(i);
1204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (st.authorityId == authority.ident) {
1205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            found = true;
1206231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
1207231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!found) {
1210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        st = new SyncStatusInfo(authority.ident);
1211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(authority.ident, st);
1212231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.totalElapsedTime = getLongColumn(c, "totalElapsedTime");
1214231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSyncs = getIntColumn(c, "numSyncs");
1215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceLocal = getIntColumn(c, "numSourceLocal");
1216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourcePoll = getIntColumn(c, "numSourcePoll");
1217231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceServer = getIntColumn(c, "numSourceServer");
1218231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceUser = getIntColumn(c, "numSourceUser");
1219231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessSource = getIntColumn(c, "lastSuccessSource");
1220231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessTime = getLongColumn(c, "lastSuccessTime");
1221231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureSource = getIntColumn(c, "lastFailureSource");
1222231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureTime = getLongColumn(c, "lastFailureTime");
1223231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureMesg = c.getString(c.getColumnIndex("lastFailureMesg"));
1224231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.pending = getIntColumn(c, "pending") != 0;
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1227231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1228231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c.close();
1229231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1230231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Retrieve the settings.
1231231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb = new SQLiteQueryBuilder();
1232231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("settings");
1233231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c = qb.query(db, null, null, null, null, null, null);
1234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (c.moveToNext()) {
1235231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String name = c.getString(c.getColumnIndex("name"));
1236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String value = c.getString(c.getColumnIndex("value"));
1237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name == null) continue;
1238231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name.equals("listen_for_tickles")) {
1239ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    setMasterSyncAutomatically(value == null || Boolean.parseBoolean(value));
1240231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else if (name.startsWith("sync_provider_")) {
1241231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    String provider = name.substring("sync_provider_".length(),
1242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            name.length());
1243ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    int i = mAuthorities.size();
1244ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    while (i > 0) {
1245ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        i--;
1246ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        AuthorityInfo authority = mAuthorities.get(i);
1247ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        if (authority.authority.equals(provider)) {
1248ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                            authority.enabled = value == null || Boolean.parseBoolean(value);
1249ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        }
1250ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    }
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1253231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.close();
1255231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1256231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db.close();
1257231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1258231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
1259231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeStatusLocked();
1260231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            (new File(path)).delete();
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1263231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1264231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_END = 0;
1265231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_ITEM = 100;
1266231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1267231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1268231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync status back in to the initial engine state.
1269231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1270231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatusLocked() {
1271231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Reading " + mStatusFile.getBaseFile());
1272231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1273231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatusFile.readFully();
1274231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1275231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1276231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1277231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
1278231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATUS_FILE_END) {
1279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATUS_FILE_ITEM) {
1280231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo status = new SyncStatusInfo(in);
1281231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.indexOfKey(status.authorityId) >= 0) {
1282231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
1283231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (DEBUG_FILE) Log.v(TAG, "Adding status for id "
1284231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                + status.authorityId);
1285231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(status.authorityId, status);
1286231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1287231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
1288231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
1289231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown status token: " + token);
1290231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1291231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1292231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1293231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1294231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial status");
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1297231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1298231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1299231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync status to the sync status file.
1300231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1301231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatusLocked() {
1302231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatusFile.getBaseFile());
1303231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1304231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
1305231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
1306231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATUS);
1307231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1308231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1310231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatusFile.startWrite();
1311231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1312231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1313231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1314231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo status = mSyncStatus.valueAt(i);
1315231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATUS_FILE_ITEM);
1316231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.writeToParcel(out, 0);
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1318231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATUS_FILE_END);
1319231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1321231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatusFile.finishWrite(fos);
1323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing status", e1);
1325231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1326231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatusFile.failWrite(fos);
1327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1329231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1331231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int PENDING_OPERATION_VERSION = 1;
1332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all pending operations back in to the initial engine state.
1335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1336231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readPendingOperationsLocked() {
1337231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Reading " + mPendingFile.getBaseFile());
1338231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1339231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mPendingFile.readFully();
1340231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1341231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1342231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1343231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int SIZE = in.dataSize();
1344231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (in.dataPosition() < SIZE) {
1345231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int version = in.readInt();
1346231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (version != PENDING_OPERATION_VERSION) {
1347231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown pending operation version "
1348231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + version + "; dropping all ops");
1349231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1350231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1351231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int authorityId = in.readInt();
1352231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int syncSource = in.readInt();
1353231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                byte[] flatExtras = in.createByteArray();
1354231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(authorityId);
1355231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
1356231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Bundle extras = null;
1357231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (flatExtras != null) {
1358231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        extras = unflattenBundle(flatExtras);
1359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1360231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    PendingOperation op = new PendingOperation(
1361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            authority.account, syncSource,
1362231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            authority.authority, extras);
1363231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.authorityId = authorityId;
1364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.flatExtras = flatExtras;
1365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + op.account
1366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " auth=" + op.authority
1367231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " src=" + op.syncSource
1368231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            + " extras=" + op.extras);
1369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mPendingOperations.add(op);
1370231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial pending operations");
1374231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1376231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writePendingOperationLocked(PendingOperation op, Parcel out) {
1378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(PENDING_OPERATION_VERSION);
1379231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(op.authorityId);
1380231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeInt(op.syncSource);
1381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (op.flatExtras == null && op.extras != null) {
1382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op.flatExtras = flattenBundle(op.extras);
1383231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1384231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        out.writeByteArray(op.flatExtras);
1385231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all currently pending ops to the pending ops file.
1389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1390231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writePendingOperationsLocked() {
1391231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int N = mPendingOperations.size();
1392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1393231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1394231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (N == 0) {
1395231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG_FILE) Log.v(TAG, "Truncating " + mPendingFile.getBaseFile());
1396231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mPendingFile.truncate();
1397231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
1398231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1399231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1400231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Writing new " + mPendingFile.getBaseFile());
1401231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mPendingFile.startWrite();
1402231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1403231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1404231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1405231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                PendingOperation op = mPendingOperations.get(i);
1406231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationLocked(op, out);
1407231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1408231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1409231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1410231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1411231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingFile.finishWrite(fos);
1412231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1413231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing pending operations", e1);
1414231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1415231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mPendingFile.failWrite(fos);
1416231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1417231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1418231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1419231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1420231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1421231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Append the given operation to the pending ops file; if unable to,
1422231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * write all pending ops.
1423231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1424231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void appendPendingOperationLocked(PendingOperation op) {
1425231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
1426231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1427231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1428231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mPendingFile.openAppend();
1429231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1430231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Failed append; writing full file");
1431231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationsLocked();
1432231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
1433231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1434231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1435231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1436231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1437231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationLocked(op, out);
1438231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1439231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1440231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1441231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing pending operations", e1);
1442231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1443231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            try {
1444231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                fos.close();
1445231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } catch (java.io.IOException e2) {
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1447231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1448231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1449231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1450231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static private byte[] flattenBundle(Bundle bundle) {
1451231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        byte[] flatData = null;
1452231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Parcel parcel = Parcel.obtain();
1453231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1454231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle.writeToParcel(parcel, 0);
1455231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            flatData = parcel.marshall();
1456231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1457231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.recycle();
1458231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1459231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return flatData;
1460231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1461231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1462231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static private Bundle unflattenBundle(byte[] flatData) {
1463231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Bundle bundle;
1464231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        Parcel parcel = Parcel.obtain();
1465231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1466231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.unmarshall(flatData, 0, flatData.length);
1467231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.setDataPosition(0);
1468231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle = parcel.readBundle();
1469231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (RuntimeException e) {
1470231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // A RuntimeException is thrown if we were unable to parse the parcel.
1471231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Create an empty parcel in this case.
1472231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            bundle = new Bundle();
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
1474231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parcel.recycle();
1475231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1476231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return bundle;
1477231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1478231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1479231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_END = 0;
1480231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM_OLD = 100;
1481231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM = 101;
1482231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1483231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1484231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync statistics back in to the initial engine state.
1485231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1486231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatisticsLocked() {
1487231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1488231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatisticsFile.readFully();
1489231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
1490231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
1491231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
1492231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
1493231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int index = 0;
1494231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATISTICS_FILE_END) {
1495231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATISTICS_FILE_ITEM
1496231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || token == STATISTICS_FILE_ITEM_OLD) {
1497231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int day = in.readInt();
1498231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (token == STATISTICS_FILE_ITEM_OLD) {
1499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        day = day - 2009 + 14245;  // Magic!
1500231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1501231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    DayStats ds = new DayStats(day);
1502231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successCount = in.readInt();
1503231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successTime = in.readLong();
1504231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureCount = in.readInt();
1505231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureTime = in.readLong();
1506231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (index < mDayStats.length) {
1507231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mDayStats[index] = ds;
1508231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        index++;
1509231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1510231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
1511231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
1512231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown stats token: " + token);
1513231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1514231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1515231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1516231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1517231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial statistics");
1518231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1519231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1520231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1521231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1522231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync statistics to the sync status file.
1523231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1524231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatisticsLocked() {
1525231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
1526231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1527231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
1528231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
1529231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATISTICS);
1530231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1531231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1532231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1533231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatisticsFile.startWrite();
1534231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
1535231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mDayStats.length;
1536231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1537231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                DayStats ds = mDayStats[i];
1538231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ds == null) {
1539231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1540231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1541231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATISTICS_FILE_ITEM);
1542231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.day);
1543231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.successCount);
1544231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.successTime);
1545231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.failureCount);
1546231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.failureTime);
1547231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1548231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATISTICS_FILE_END);
1549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
1550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
1551231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1552231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatisticsFile.finishWrite(fos);
1553231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1554231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing stats", e1);
1555231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1556231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatisticsFile.failWrite(fos);
1557231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1561