SyncStorageEngine.java revision 55280a91884b9256e8db6af6a09f28b3feeaa9d8
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
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
29231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.database.sqlite.SQLiteException;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder;
31231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Bundle;
32231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Environment;
33231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Handler;
34231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Message;
35231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel;
36231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteCallbackList;
37231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteException;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
39231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.SparseArray;
40231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.Xml;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
42231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.File;
43231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileInputStream;
44231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileOutputStream;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
46231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Calendar;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
48231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Iterator;
49231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.TimeZone;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
52231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Singleton that tracks the sync data and overall sync
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * history on the device.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
57231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornpublic class SyncStorageEngine extends Handler {
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SyncManager";
59231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final boolean DEBUG = false;
60231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final boolean DEBUG_FILE = false;
61231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
62231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // @VisibleForTesting
63231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
65231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync start event. */
66231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_START = 0;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
68231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync stop event. */
69231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_STOP = 1;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
71231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
72231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync event types. */
73231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] EVENTS = { "START", "STOP" };
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
75231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a server-initiated sync. */
76231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_SERVER = 0;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
78231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a local-initiated sync. */
79231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_LOCAL = 1;
80231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
81231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Enum value for a poll-based sync (e.g., upon connection to
82231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * network)
83231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
84231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_POLL = 2;
85231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
86231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a user-initiated sync. */
87231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_USER = 3;
88231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
89231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
90231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync source types. */
91231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] SOURCES = { "SERVER",
92231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "LOCAL",
93231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "POLL",
94231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "USER" };
95231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
96231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // Error types
97231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
98231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int ERROR_AUTHENTICATION = 2;
99231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int ERROR_IO = 3;
100231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int ERROR_PARSE = 4;
101231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int ERROR_CONFLICT = 5;
102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int ERROR_TOO_MANY_DELETIONS = 6;
103231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int ERROR_TOO_MANY_RETRIES = 7;
104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int ERROR_INTERNAL = 8;
105231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
106231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // The MESG column will contain one of these or one of the Error types.
107231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_SUCCESS = "success";
108231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_CANCELED = "canceled";
109231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int CHANGE_SETTINGS = 1<<0;
111231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int CHANGE_PENDING = 1<<1;
112231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int CHANGE_ACTIVE = 1<<2;
113231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int CHANGE_STATUS = 1<<3;
114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int CHANGE_ALL = 0x7fffffff;
115231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int MAX_HISTORY = 15;
117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATUS = 1;
119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATUS_DELAY = 1000*60*10; // 10 minutes
120231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
121231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATISTICS = 2;
122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATISTICS_DELAY = 1000*60*30; // 1/2 hour
123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class PendingOperation {
125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String account;
126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int syncSource;
127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String authority;
128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final Bundle extras;        // note: read-only.
129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int authorityId;
131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        byte[] flatExtras;
132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
133231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        PendingOperation(String account, int source,
134231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String authority, Bundle extras) {
135231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = source;
137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = authority;
138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = extras != null ? new Bundle(extras) : extras;
139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authorityId = -1;
140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        PendingOperation(PendingOperation other) {
143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = other.account;
144231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = other.syncSource;
145231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = other.authority;
146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = other.extras;
147231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authorityId = other.authorityId;
148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
149231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
150231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
151231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static class AccountInfo {
152231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String account;
153231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final HashMap<String, AuthorityInfo> authorities =
154231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                new HashMap<String, AuthorityInfo>();
155231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
156231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo(String account) {
157231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
158231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
159231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class AuthorityInfo {
162231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String account;
163231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final String authority;
164231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int ident;
165231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean enabled;
166231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
167231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo(String account, String authority, int ident) {
168231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.account = account;
169231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authority = authority;
170231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.ident = ident;
171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            enabled = true;
172231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
174231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
175231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class SyncHistoryItem {
176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int authorityId;
177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int historyId;
178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long eventTime;
179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long elapsedTime;
180231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int source;
181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int event;
182231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long upstreamActivity;
183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long downstreamActivity;
184231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String mesg;
185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class DayStats {
188231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public final int day;
189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int successCount;
190231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long successTime;
191231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int failureCount;
192231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long failureTime;
193231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
194231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public DayStats(int day) {
195231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.day = day;
196231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
197231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
199231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // Primary list of all syncable authorities.  Also our global lock.
200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<AuthorityInfo> mAuthorities =
201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<AuthorityInfo>();
202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final HashMap<String, AccountInfo> mAccounts =
204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        new HashMap<String, AccountInfo>();
205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
206231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<PendingOperation> mPendingOperations =
207231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<PendingOperation>();
208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private ActiveSyncInfo mActiveSync;
210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<SyncStatusInfo> mSyncStatus =
212231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<SyncStatusInfo>();
213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
214231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<SyncHistoryItem> mSyncHistory =
215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<SyncHistoryItem>();
216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
217231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final RemoteCallbackList<ISyncStatusObserver> mChangeListeners
218231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            = new RemoteCallbackList<ISyncStatusObserver>();
219231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
220231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // We keep 4 weeks of stats.
221231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final DayStats[] mDayStats = new DayStats[7*4];
222231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Calendar mCal;
223231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYear;
224231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYearInDays;
225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
226231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Context mContext;
227231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static volatile SyncStorageEngine sSyncStorageEngine = null;
228231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
229231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
230231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the core engine state: all accounts and the
231231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * settings for them.  It must never be lost, and should be changed
232231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * infrequently, so it is stored as an XML file.
233231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mAccountInfoFile;
235231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the current sync status.  We would like to retain
238231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * it across boots, but its loss is not the end of the world, so we store
239231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * this information as binary data.
240231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
241231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatusFile;
242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
243231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
244231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains sync statistics.  This is purely debugging information
245231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so is written infrequently and can be thrown away at any time.
246231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
247231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatisticsFile;
248231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
249231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
250231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the pending sync operations.  It is a binary file,
251231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * which must be updated every time an operation is added or removed,
252231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so we have special handling of it.
253231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
254231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mPendingFile;
255231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int PENDING_FINISH_TO_WRITE = 4;
256231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNumPendingFinished = 0;
257231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
258231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNextHistoryId = 0;
259231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private boolean mListenForTickles = true;
260231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private SyncStorageEngine(Context context) {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sSyncStorageEngine = this;
264231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
265231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
266231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
267231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File dataDir = Environment.getDataDirectory();
268231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File systemDir = new File(dataDir, "system");
269231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File syncDir = new File(systemDir, "sync");
270231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
271231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
272231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mPendingFile = new AtomicFile(new File(syncDir, "pending.bin"));
273231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
274231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
275231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readAccountInfoLocked();
276231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatusLocked();
277231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readPendingOperationsLocked();
278231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatisticsLocked();
279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readLegacyAccountInfoLocked();
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine newTestInstance(Context context) {
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return new SyncStorageEngine(context);
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void init(Context context) {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine != null) {
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("already initialized");
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sSyncStorageEngine = new SyncStorageEngine(context);
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine getSingleton() {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine == null) {
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("not initialized");
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sSyncStorageEngine;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
300231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    @Override public void handleMessage(Message msg) {
301231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (msg.what == MSG_WRITE_STATUS) {
302231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            synchronized (mAccounts) {
303231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
304231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
305231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } else if (msg.what == MSG_WRITE_STATISTICS) {
306231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            synchronized (mAccounts) {
307231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
310231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
311231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
312231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
313231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
314231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.register(callback, mask);
315231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
316231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
317231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
318231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void removeStatusChangeListener(ISyncStatusObserver callback) {
319231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.unregister(callback);
321231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void reportChange(int which) {
325231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        ArrayList<ISyncStatusObserver> reports = null;
326231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mChangeListeners.beginBroadcast();
328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
329231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Integer mask = (Integer)mChangeListeners.getBroadcastCookie(i);
331231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if ((which & mask.intValue()) == 0) {
332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (reports == null) {
335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports = new ArrayList<ISyncStatusObserver>(i);
336231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
337231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                reports.add(mChangeListeners.getBroadcastItem(i));
338231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
339231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
340231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
341231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG) Log.v(TAG, "reportChange " + which + " to: " + reports);
342231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
343231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (reports != null) {
344231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = reports.size();
345231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
346231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
347231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
348231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports.get(i).onStatusChanged(which);
349231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (RemoteException e) {
350231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // The remote callback list will take care of this for us.
351231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
352231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
353231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
354231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
355231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
356231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean getSyncProviderAutomatically(String account, String providerName) {
357231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
358231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (account != null) {
359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(account, providerName,
360231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "getSyncProviderAutomatically");
361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return authority != null ? authority.enabled : false;
362231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
363231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mAuthorities.size();
365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
367231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(i);
368231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority.authority.equals(providerName)
369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        && authority.enabled) {
370231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void setSyncProviderAutomatically(String account, String providerName, boolean sync) {
378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
379231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (account != null) {
380231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(account, providerName,
381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "setSyncProviderAutomatically");
382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
383231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    authority.enabled = sync;
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
385231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else {
386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                int i = mAuthorities.size();
387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                while (i > 0) {
388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    i--;
389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    AuthorityInfo authority = mAuthorities.get(i);
390231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (authority.account.equals(account)
391231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            && authority.authority.equals(providerName)) {
392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        authority.enabled = sync;
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
396231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
398231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
399231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        reportChange(CHANGE_SETTINGS);
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
402231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void setListenForNetworkTickles(boolean flag) {
403231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
404231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mListenForTickles = flag;
405231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
407231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        reportChange(CHANGE_SETTINGS);
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
410231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean getListenForNetworkTickles() {
411231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
412231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mListenForTickles;
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
415231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
416231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public AuthorityInfo getAuthority(String account, String authority) {
417231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
418231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return getAuthorityLocked(account, authority, null);
419231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
421231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
422231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public AuthorityInfo getAuthority(int authorityId) {
423231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
424231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mAuthorities.get(authorityId);
425231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
426231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
427231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
429231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Returns true if there is currently a sync operation for the given
430231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * account or authority in the pending list, or actively being processed.
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
432231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean isSyncActive(String account, String authority) {
433231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
434231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mPendingOperations.size();
435231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
436231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
437231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // TODO(fredq): this probably shouldn't be considering
438231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // pending operations.
439231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                PendingOperation op = mPendingOperations.get(i);
440231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (op.account.equals(account) && op.authority.equals(authority)) {
441231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
442231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
443231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
444231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
445231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mActiveSync != null) {
446231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = getAuthority(mActiveSync.authorityId);
447231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo != null && ainfo.account.equals(account)
448231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        && ainfo.authority.equals(authority)) {
449231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
450231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
451231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
453231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
454231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
455231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
456231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
457231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public PendingOperation insertIntoPending(PendingOperation op) {
458231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
459231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertIntoPending: account=" + op.account
460231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
461231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
462231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
463231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
464231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getOrCreateAuthorityLocked(op.account,
465231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    op.authority,
466231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    -1 /* desired identifier */,
467231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    true /* write accounts to storage */);
468231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
469231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return null;
470231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
471231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
472231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op = new PendingOperation(op);
473231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            op.authorityId = authority.ident;
474231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.add(op);
475231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            appendPendingOperationLocked(op);
476231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
477231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
478231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.pending = true;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
480231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
481231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        reportChange(CHANGE_PENDING);
482231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return op;
483231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
485231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean deleteFromPending(PendingOperation op) {
486231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean res = false;
487231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
488231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "deleteFromPending: account=" + op.account
489231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + op.authority
490231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " src=" + op.syncSource
491231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " extras=" + op.extras);
492231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mPendingOperations.remove(op)) {
493231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mPendingOperations.size() == 0
494231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || mNumPendingFinished >= PENDING_FINISH_TO_WRITE) {
495231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writePendingOperationsLocked();
496231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished = 0;
497231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
498231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished++;
499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
500231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
501231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(op.account, op.authority,
502231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "deleteFromPending");
503231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
504231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.v(TAG, "removing - " + authority);
505231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    final int N = mPendingOperations.size();
506231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean morePending = false;
507231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (int i=0; i<N; i++) {
508231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        PendingOperation cur = mPendingOperations.get(i);
509231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (cur.account.equals(op.account)
510231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                && cur.authority.equals(op.authority)) {
511231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            morePending = true;
512231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
513231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
514231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
515231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
516231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!morePending) {
517231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (DEBUG) Log.v(TAG, "no more pending!");
518231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
519231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
520231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
521231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
522231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
523231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                res = true;
524231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
525231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
526231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
527231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        reportChange(CHANGE_PENDING);
528231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return res;
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
531231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int clearPending() {
532231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int num;
533231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
534231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "clearPending");
535231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            num = mPendingOperations.size();
536231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mPendingOperations.clear();
537231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
538231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
539231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mSyncStatus.get(i).pending = false;
540231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
541231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writePendingOperationsLocked();
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
543231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        reportChange(CHANGE_PENDING);
544231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return num;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
548231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return a copy of the current array of pending operations.  The
549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * PendingOperation objects are the real objects stored inside, so that
550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * they can be used with deleteFromPending().
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
552231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<PendingOperation> getPendingOperations() {
553231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
554231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return new ArrayList<PendingOperation>(mPendingOperations);
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
557231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
559231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the number of currently pending operations.
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int getPendingOperationCount() {
562231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mPendingOperations.size();
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
566231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
568231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the set of account has changed, given the new array of
569231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active accounts.
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
571231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void doDatabaseCleanup(String[] accounts) {
572231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
573231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.w(TAG, "Updating for new accounts...");
574231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SparseArray<AuthorityInfo> removing = new SparseArray<AuthorityInfo>();
575231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Iterator<AccountInfo> accIt = mAccounts.values().iterator();
576231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (accIt.hasNext()) {
577231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AccountInfo acc = accIt.next();
578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!ArrayUtils.contains(accounts, acc.account)) {
579231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // This account no longer exists...
580231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (DEBUG) Log.w(TAG, "Account removed: " + acc.account);
581231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (AuthorityInfo auth : acc.authorities.values()) {
582231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        removing.put(auth.ident, auth);
583231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
584231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    accIt.remove();
585231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
586231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
587231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
588231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Clean out all data structures.
589231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = removing.size();
590231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (i > 0) {
591231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                while (i > 0) {
592231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    i--;
593231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int ident = removing.keyAt(i);
594231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mAuthorities.remove(ident);
595231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int j = mSyncStatus.size();
596231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
597231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
598231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncStatus.keyAt(j) == ident) {
599231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncStatus.remove(mSyncStatus.keyAt(j));
600231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
601231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
602231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    j = mSyncHistory.size();
603231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
604231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
605231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncHistory.get(j).authorityId == ident) {
606231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncHistory.remove(j);
607231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
608231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
609231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
610231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
611231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
612231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationsLocked();
613231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
614231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
618231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
619231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the currently active sync is changing (there can only be
620231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * one at a time).  Either supply a valid ActiveSyncContext with information
621231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * about the sync, or null to stop the currently active sync.
622231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
623231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void setActiveSync(SyncManager.ActiveSyncContext activeSyncContext) {
624231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
625231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (activeSyncContext != null) {
626231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: account="
627231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + activeSyncContext.mSyncOperation.account
628231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " auth=" + activeSyncContext.mSyncOperation.authority
629231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " src=" + activeSyncContext.mSyncOperation.syncSource
630231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        + " extras=" + activeSyncContext.mSyncOperation.extras);
631231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mActiveSync != null) {
632231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "setActiveSync called with existing active sync!");
633231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
634231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = getAuthorityLocked(
635231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.account,
636231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mSyncOperation.authority,
637231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        "setActiveSync");
638231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority == null) {
639231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return;
640231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
641231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = new ActiveSyncInfo(authority.ident,
642231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        authority.account, authority.authority,
643231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        activeSyncContext.mStartTime);
644231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else {
645231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (DEBUG) Log.v(TAG, "setActiveSync: null");
646231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mActiveSync = null;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
649231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
650231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        reportChange(CHANGE_ACTIVE);
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
653231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
654231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * To allow others to send active change reports, to poke clients.
655231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
656231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void reportActiveChange() {
657231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        reportChange(CHANGE_ACTIVE);
658231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
659231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
660231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
661231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Note that sync has started for the given account and authority.
662231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
663231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public long insertStartSyncEvent(String accountName, String authorityName,
664231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long now, int source) {
665231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long id;
666231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
667231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "insertStartSyncEvent: account=" + accountName
668231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    + " auth=" + authorityName + " source=" + source);
669231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            AuthorityInfo authority = getAuthorityLocked(accountName, authorityName,
670231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    "insertStartSyncEvent");
671231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
672231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return -1;
673231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
674231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = new SyncHistoryItem();
675231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.authorityId = authority.ident;
676231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.historyId = mNextHistoryId++;
677231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mNextHistoryId < 0) mNextHistoryId = 0;
678231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.eventTime = now;
679231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.source = source;
680231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_START;
681231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncHistory.add(0, item);
682231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (mSyncHistory.size() > MAX_HISTORY) {
683231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mSyncHistory.remove(mSyncHistory.size()-1);
684231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
685231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            id = item.historyId;
686231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "returning historyId " + id);
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
688231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
689231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        reportChange(CHANGE_STATUS);
690231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return id;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
693231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
694231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long downstreamActivity, long upstreamActivity) {
695231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
696231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG) Log.v(TAG, "stopSyncEvent: historyId=" + historyId);
697231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = null;
698231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncHistory.size();
699231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
700231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
701231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = mSyncHistory.get(i);
702231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (item.historyId == historyId) {
703231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
704231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
705231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = null;
706231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
707231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
708231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (item == null) {
709231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, "stopSyncEvent: no history for id " + historyId);
710231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
711231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
712231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
713231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.elapsedTime = elapsedTime;
714231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_STOP;
715231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.mesg = resultMessage;
716231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.downstreamActivity = downstreamActivity;
717231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.upstreamActivity = upstreamActivity;
718231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
719231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(item.authorityId);
720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
721231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.numSyncs++;
722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.totalElapsedTime += elapsedTime;
723231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            switch (item.source) {
724231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_LOCAL:
725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceLocal++;
726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_POLL:
728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourcePoll++;
729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
730231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_USER:
731231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceUser++;
732231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
733231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_SERVER:
734231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceServer++;
735231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
736231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
737231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
738231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatisticsNow = false;
73955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            int day = getCurrentDayLocked();
740231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mDayStats[0] == null) {
741231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
742231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (day != mDayStats[0].day) {
743231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                System.arraycopy(mDayStats, 0, mDayStats, 1, mDayStats.length-1);
744231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
745231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsNow = true;
746231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (mDayStats[0] == null) {
747231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
748231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final DayStats ds = mDayStats[0];
749231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
750231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final long lastSyncTime = (item.eventTime + elapsedTime);
751231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatusNow = false;
752231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (MESG_SUCCESS.equals(resultMessage)) {
753231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // - if successful, update the successful columns
754231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastSuccessTime == 0 || status.lastFailureTime != 0) {
755231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
756231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
757231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessTime = lastSyncTime;
758231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessSource = item.source;
759231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = 0;
760231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = -1;
761231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = null;
762231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.initialFailureTime = 0;
763231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successCount++;
764231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successTime += elapsedTime;
765231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!MESG_CANCELED.equals(resultMessage)) {
766231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastFailureTime == 0) {
767231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
768231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
769231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = lastSyncTime;
770231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = item.source;
771231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = resultMessage;
772231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.initialFailureTime == 0) {
773231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.initialFailureTime = lastSyncTime;
774231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
775231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureCount++;
776231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureTime += elapsedTime;
777231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
778231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
779231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatusNow) {
780231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
781231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATUS)) {
782231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATUS),
783231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATUS_DELAY);
784231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
785231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatisticsNow) {
786231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
787231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATISTICS)) {
788231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATISTICS),
789231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATISTICS_DELAY);
790231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
792231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
793231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        reportChange(CHANGE_STATUS);
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
797231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the currently active sync information, or null if there is no
798231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active sync.  Note that the returned object is the real, live active
799231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync object, so be careful what you do with it.
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
801231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ActiveSyncInfo getActiveSync() {
802231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
803231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mActiveSync;
804231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
806231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
807231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
808231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
809231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
810231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
811231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
812231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncStatusInfo> getSyncStatus() {
813231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
814231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
815231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncStatusInfo> ops = new ArrayList<SyncStatusInfo>(N);
816231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
817231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ops.add(mSyncStatus.valueAt(i));
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
819231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ops;
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
822231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
823231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
824231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Returns the status that matches the authority. If there are multiples accounts for
825231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * the authority, the one with the latest "lastSuccessTime" status is returned.
826231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authority the authority whose row should be selected
827231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @return the SyncStatusInfo for the authority, or null if none exists
828231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
829231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public SyncStatusInfo getStatusByAuthority(String authority) {
830231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
831231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo best = null;
832231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
833231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
834231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo cur = mSyncStatus.get(i);
835231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
836231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo != null && ainfo.authority.equals(authority)) {
837231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (best == null) {
838231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        best = cur;
839231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    } else if (best.lastSuccessTime > cur.lastSuccessTime) {
840231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        best = cur;
841231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
842231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
843231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
844231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return best;
845231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
847231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
848231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
849231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return true if the pending status is true of any matching authorities.
850231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
851231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean isAuthorityPending(String account, String authority) {
852231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
853231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
854231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
855231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo cur = mSyncStatus.get(i);
856231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
857231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo == null) {
858231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
859231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
860231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (account != null && !ainfo.account.equals(account)) {
861231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
862231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
863231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo.authority.equals(authority) && cur.pending) {
864231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
867231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
872231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
873231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
874231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
875231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
876231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncHistoryItem> getSyncHistory() {
877231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
878231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncHistory.size();
879231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncHistoryItem> items = new ArrayList<SyncHistoryItem>(N);
880231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
881231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                items.add(mSyncHistory.get(i));
882231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
883231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return items;
884231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
885231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
886231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
887231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
888231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current per-day statistics.  Note
889231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
890231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
891231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
892231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public DayStats[] getDayStatistics() {
893231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
894231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            DayStats[] ds = new DayStats[mDayStats.length];
895231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            System.arraycopy(mDayStats, 0, ds, 0, ds.length);
896231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ds;
897231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
898231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
899231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
900231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If sync is failing for any of the provider/accounts then determine the time at which it
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * started failing and return the earliest time over all the provider/accounts. If none are
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * failing then return 0.
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public long getInitialSyncFailureTime() {
906231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
907231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (!mListenForTickles) {
908231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return 0;
909231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
910231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
911231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long oldest = 0;
912231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncStatus.size();
913231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
914231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
915231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo stats = mSyncStatus.valueAt(i);
916231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(stats.authorityId);
917231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null && authority.enabled) {
918231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (oldest == 0 || stats.initialFailureTime < oldest) {
919231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        oldest = stats.initialFailureTime;
920231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
921231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
922231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
923231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
924231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return oldest;
925231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
926231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
927231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
92855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private int getCurrentDayLocked() {
929231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal.setTimeInMillis(System.currentTimeMillis());
930231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
931231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (mYear != mCal.get(Calendar.YEAR)) {
932231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYear = mCal.get(Calendar.YEAR);
933231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.clear();
934231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.set(Calendar.YEAR, mYear);
935231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYearInDays = (int)(mCal.getTimeInMillis()/86400000);
936231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
937231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return dayOfYear + mYearInDays;
938231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
939231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
940231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
941231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Retrieve an authority, returning null if one does not exist.
942231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     *
943231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param accountName The name of the account for the authority.
944231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param authorityName The name of the authority itself.
945231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param tag If non-null, this will be used in a log message if the
946231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * requested authority does not exist.
947231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
948231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private AuthorityInfo getAuthorityLocked(String accountName, String authorityName,
949231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tag) {
950231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
951231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
952231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
953231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, tag + ": unknown account " + accountName);
954231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
955231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
956231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
957231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
958231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
959231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (tag != null) {
960231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, tag + ": unknown authority " + authorityName);
961231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
962231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return null;
963231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
964231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
965231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
966231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
967231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
968231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private AuthorityInfo getOrCreateAuthorityLocked(String accountName,
969231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String authorityName, int ident, boolean doWrite) {
970231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AccountInfo account = mAccounts.get(accountName);
971231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (account == null) {
972231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account = new AccountInfo(accountName);
973231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccounts.put(accountName, account);
974231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
975231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        AuthorityInfo authority = account.authorities.get(authorityName);
976231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (authority == null) {
977231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (ident < 0) {
978231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // Look for a new identifier for this authority.
979231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                final int N = mAuthorities.size();
980231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ident = 0;
981231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                for (int i=0; i<N; i++) {
982231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.valueAt(i).ident > ident) {
983231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        break;
984231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
985231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ident++;
986231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
987231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
988231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            authority = new AuthorityInfo(accountName, authorityName, ident);
989231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            account.authorities.put(authorityName, authority);
990231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAuthorities.put(ident, authority);
991231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (doWrite) {
992231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
993231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
994231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
995231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
996231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
997231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
998231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
999231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private SyncStatusInfo getOrCreateSyncStatusLocked(int authorityId) {
1000231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SyncStatusInfo status = mSyncStatus.get(authorityId);
1001231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (status == null) {
1002231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status = new SyncStatusInfo(authorityId);
1003231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncStatus.put(authorityId, status);
1004231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1005231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return status;
1006231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1007231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
100855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    public void writeAllState() {
100955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        synchronized (mAuthorities) {
101055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Account info is always written so no need to do it here.
101155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
101255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            if (mNumPendingFinished > 0) {
101355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                // Only write these if they are out of date.
101455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                writePendingOperationsLocked();
101555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
101655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
101755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Just always write these...  they are likely out of date.
101855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatusLocked();
101955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatisticsLocked();
102055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
102155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
102255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
1023231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1024231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all account information back in to the initial engine state.
1025231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1026231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readAccountInfoLocked() {
1027231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileInputStream fis = null;
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1029231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fis = mAccountInfoFile.openRead();
1030231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading " + mAccountInfoFile.getBaseFile());
1031231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlPullParser parser = Xml.newPullParser();
1032231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parser.setInput(fis, null);
1033231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int eventType = parser.getEventType();
1034231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (eventType != XmlPullParser.START_TAG) {
1035231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1036231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1037231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tagName = parser.getName();
1038231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if ("accounts".equals(tagName)) {
1039231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String listen = parser.getAttributeValue(
1040231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        null, "listen-for-tickles");
1041231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mListenForTickles = listen == null
1042231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            || Boolean.parseBoolean(listen);
1043231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1044231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                do {
1045231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (eventType == XmlPullParser.START_TAG
1046231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            && parser.getDepth() == 2) {
1047231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        tagName = parser.getName();
1048231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if ("authority".equals(tagName)) {
1049231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            int id = -1;
1050231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            try {
1051231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                id = Integer.parseInt(parser.getAttributeValue(
1052231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "id"));
1053231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            } catch (NumberFormatException e) {
1054231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            } catch (NullPointerException e) {
1055231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1056231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            if (id >= 0) {
1057231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                String accountName = parser.getAttributeValue(
1058231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "account");
1059231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                String authorityName = parser.getAttributeValue(
1060231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "authority");
1061231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                String enabled = parser.getAttributeValue(
1062231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        null, "enabled");
1063231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                AuthorityInfo authority = mAuthorities.get(id);
1064231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                if (DEBUG_FILE) Log.v(TAG, "Adding authority: account="
1065231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        + accountName + " auth=" + authorityName
1066231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        + " enabled=" + enabled);
1067231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                if (authority == null) {
1068231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    if (DEBUG_FILE) Log.v(TAG, "Creating entry");
1069231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    authority = getOrCreateAuthorityLocked(
1070231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                        accountName, authorityName, id, false);
1071231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                }
1072231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                if (authority != null) {
1073231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    authority.enabled = enabled == null
1074231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                            || Boolean.parseBoolean(enabled);
1075231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                } else {
1076231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                    Log.w(TAG, "Failure adding authority: account="
1077231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                            + accountName + " auth=" + authorityName
1078231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                            + " enabled=" + enabled);
1079231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                }
1080231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1081231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1082231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1083231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    eventType = parser.next();
1084231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } while (eventType != XmlPullParser.END_DOCUMENT);
1085231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1086231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (XmlPullParserException e) {
1087231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error reading accounts", e);
1088231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1089231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis == null) Log.i(TAG, "No initial accounts");
1090231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            else Log.w(TAG, "Error reading accounts", e);
1091231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
1092231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis != null) {
1093231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
1094231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    fis.close();
1095231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (java.io.IOException e1) {
1096231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1097231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1098231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1099231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1100231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1101231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all account information to the account file.
1103231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeAccountInfoLocked() {
1105231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
1106231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
1107231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1108231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1109231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mAccountInfoFile.startWrite();
1110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlSerializer out = new FastXmlSerializer();
1111231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setOutput(fos, "utf-8");
1112231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startDocument(null, true);
1113231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1115231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startTag(null, "accounts");
1116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (!mListenForTickles) {
1117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "listen-for-tickles", "false");
1118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1119231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1120231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mAuthorities.size();
1121231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = mAuthorities.get(i);
1123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.startTag(null, "authority");
1124231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "id", Integer.toString(authority.ident));
1125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "account", authority.account);
1126231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "authority", authority.authority);
1127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (!authority.enabled) {
1128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    out.attribute(null, "enabled", "false");
1129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.endTag(null, "authority");
1131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1133231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endTag(null, "accounts");
1134231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1135231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endDocument();
1136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccountInfoFile.finishWrite(fos);
1138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
1139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing accounts", e1);
1140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
1141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mAccountInfoFile.failWrite(fos);
1142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1144231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1145231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static int getIntColumn(Cursor c, String name) {
1147231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getInt(c.getColumnIndex(name));
1148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1149231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1150231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static long getLongColumn(Cursor c, String name) {
1151231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getLong(c.getColumnIndex(name));
1152231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1153231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1154231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1155231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Load sync engine state from the old syncmanager database, and then
1156231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * erase it.  Note that we don't deal with pending operations, active
1157231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync, or history.
1158231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1159231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readLegacyAccountInfoLocked() {
1160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // Look for old database to initialize from.
1161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File file = mContext.getDatabasePath("syncmanager.db");
1162231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (!file.exists()) {
1163231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
1164231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1165231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String path = file.getPath();
1166231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SQLiteDatabase db = null;
1167231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
1168231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db = SQLiteDatabase.openDatabase(path, null,
1169231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SQLiteDatabase.OPEN_READONLY);
1170231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (SQLiteException e) {
1171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1172231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (db != null) {
1174231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Copy in all of the status information, as well as accounts.
1175231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (DEBUG_FILE) Log.v(TAG, "Reading legacy sync accounts db");
1176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
1177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("stats, status");
1178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            HashMap<String,String> map = new HashMap<String,String>();
1179231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("_id", "status._id as _id");
1180231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("account", "stats.account as account");
1181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("authority", "stats.authority as authority");
1182231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("totalElapsedTime", "totalElapsedTime");
1183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSyncs", "numSyncs");
1184231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceLocal", "numSourceLocal");
1185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourcePoll", "numSourcePoll");
1186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceServer", "numSourceServer");
1187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceUser", "numSourceUser");
1188231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessSource", "lastSuccessSource");
1189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessTime", "lastSuccessTime");
1190231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureSource", "lastFailureSource");
1191231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureTime", "lastFailureTime");
1192231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureMesg", "lastFailureMesg");
1193231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("pending", "pending");
1194231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setProjectionMap(map);
1195231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.appendWhere("stats._id = status.stats_id");
1196231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Cursor c = qb.query(db, null, null, null, null, null, null);
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (c.moveToNext()) {
1198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String accountName = c.getString(c.getColumnIndex("account"));
1199231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String authorityName = c.getString(c.getColumnIndex("authority"));
1200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo authority = this.getOrCreateAuthorityLocked(
1201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        accountName, authorityName, -1, false);
1202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
1203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int i = mSyncStatus.size();
1204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean found = false;
1205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo st = null;
1206231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (i > 0) {
1207231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        i--;
1208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        st = mSyncStatus.get(i);
1209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (st.authorityId == authority.ident) {
1210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            found = true;
1211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
1212231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1214231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!found) {
1215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        st = new SyncStatusInfo(authority.ident);
1216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(authority.ident, st);
1217231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1218231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.totalElapsedTime = getLongColumn(c, "totalElapsedTime");
1219231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSyncs = getIntColumn(c, "numSyncs");
1220231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceLocal = getIntColumn(c, "numSourceLocal");
1221231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourcePoll = getIntColumn(c, "numSourcePoll");
1222231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceServer = getIntColumn(c, "numSourceServer");
1223231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceUser = getIntColumn(c, "numSourceUser");
1224231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessSource = getIntColumn(c, "lastSuccessSource");
1225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessTime = getLongColumn(c, "lastSuccessTime");
1226231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureSource = getIntColumn(c, "lastFailureSource");
1227231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureTime = getLongColumn(c, "lastFailureTime");
1228231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureMesg = c.getString(c.getColumnIndex("lastFailureMesg"));
1229231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.pending = getIntColumn(c, "pending") != 0;
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1231231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1232231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1233231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c.close();
1234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
1235231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Retrieve the settings.
1236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb = new SQLiteQueryBuilder();
1237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("settings");
1238231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c = qb.query(db, null, null, null, null, null, null);
1239231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (c.moveToNext()) {
1240231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String name = c.getString(c.getColumnIndex("name"));
1241231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String value = c.getString(c.getColumnIndex("value"));
1242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name == null) continue;
1243231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name.equals("listen_for_tickles")) {
1244231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    setListenForNetworkTickles(value == null
1245231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            || Boolean.parseBoolean(value));
1246231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else if (name.startsWith("sync_provider_")) {
1247231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    String provider = name.substring("sync_provider_".length(),
1248231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            name.length());
1249231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    setSyncProviderAutomatically(null, provider,
1250231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            value == null || Boolean.parseBoolean(value));
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) {
1446231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
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