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
177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.android.server.content;
18a3cdaa5337fa573c4c61770195d6232c2e587090Jason parks
19d9d2f1140b52fd0c014e9deac59f6000564b7e84Fred Quintanaimport android.accounts.Account;
20f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasaniimport android.accounts.AccountAndUser;
21fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williamsimport android.content.ComponentName;
227a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.ContentResolver;
237a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.Context;
247a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.ISyncStatusObserver;
257a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.PeriodicSync;
267a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.SyncInfo;
2756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williamsimport android.content.SyncRequest;
287a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.SyncStatusInfo;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
31231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.database.sqlite.SQLiteException;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder;
33231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Bundle;
34231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Environment;
35231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Handler;
36231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Message;
37231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.Parcel;
38231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteCallbackList;
39231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.os.RemoteException;
4056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williamsimport android.os.UserHandle;
4139606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
437a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.util.Pair;
44231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.SparseArray;
4556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williamsimport android.util.ArrayMap;
46231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport android.util.Xml;
477a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey
487a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.annotations.VisibleForTesting;
497a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.util.ArrayUtils;
507a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer;
517a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey
527a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser;
537a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException;
547a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
56231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.File;
57231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileInputStream;
58231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.io.FileOutputStream;
59ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williamsimport java.io.IOException;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
61231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Calendar;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
63231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornimport java.util.Iterator;
647a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport java.util.List;
6569d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharmaimport java.util.Random;
661125d780a8b61703b8eb28c5c77dac5f3f0022ddJason parksimport java.util.TimeZone;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
69231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn * Singleton that tracks the sync data and overall sync
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * history on the device.
71360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache *
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
74231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackbornpublic class SyncStorageEngine extends Handler {
7504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String TAG = "SyncManager";
77ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    private static final String TAG_FILE = "SyncManagerFile";
78360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
7904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private static final String XML_ATTR_NEXT_AUTHORITY_ID = "nextAuthorityId";
8004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private static final String XML_ATTR_LISTEN_FOR_TICKLES = "listen-for-tickles";
8169d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma    private static final String XML_ATTR_SYNC_RANDOM_OFFSET = "offsetInSeconds";
8204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private static final String XML_ATTR_ENABLED = "enabled";
8304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private static final String XML_ATTR_USER = "user";
8404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private static final String XML_TAG_LISTEN_FOR_TICKLES = "listenForTickles";
8504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
86fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** Default time for a periodic sync. */
87c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private static final long DEFAULT_POLL_FREQUENCY_SECONDS = 60 * 60 * 24; // One day
88c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
89fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** Percentage of period that is flex by default, if no flex is set. */
90fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    private static final double DEFAULT_FLEX_PERCENT_SYNC = 0.04;
91fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
92fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /** Lower bound on sync time from which we assign a default flex time. */
93fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    private static final long DEFAULT_MIN_FLEX_ALLOWED_SECS = 5;
94fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
958b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @VisibleForTesting
96231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
98231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync start event. */
99231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_START = 0;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
101231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a sync stop event. */
102231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int EVENT_STOP = 1;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
105231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync event types. */
106231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] EVENTS = { "START", "STOP" };
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
108231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a server-initiated sync. */
109231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_SERVER = 0;
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
111231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a local-initiated sync. */
112231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_LOCAL = 1;
11356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /** Enum value for a poll-based sync (e.g., upon connection to network) */
114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_POLL = 2;
115231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** Enum value for a user-initiated sync. */
117231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int SOURCE_USER = 3;
118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
119c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /** Enum value for a periodic sync. */
120c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public static final int SOURCE_PERIODIC = 4;
12156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
12256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /** Enum value for a sync started for a service. */
12356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static final int SOURCE_SERVICE = 5;
124c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
125307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    public static final long NOT_IN_BACKOFF_MODE = -1;
126307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // TODO: i18n -- grab these out of resources.
128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /** String names for the sync source types. */
129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String[] SOURCES = { "SERVER",
130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "LOCAL",
131231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                                             "POLL",
132c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                             "USER",
13356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                             "PERIODIC",
13456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                             "SERVICE"};
135231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // The MESG column will contain one of these or one of the Error types.
137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_SUCCESS = "success";
138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final String MESG_CANCELED = "canceled";
139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
140a33e3f79259b56b03c7912af35944f34ad190e3cDianne Hackborn    public static final int MAX_HISTORY = 100;
141360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATUS = 1;
143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATUS_DELAY = 1000*60*10; // 10 minutes
144360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
145231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int MSG_WRITE_STATISTICS = 2;
146231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final long WRITE_STATISTICS_DELAY = 1000*60*30; // 1/2 hour
1478294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato
1488294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato    private static final boolean SYNC_ENABLED_DEFAULT = false;
149360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
150c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana    // the version of the accounts xml file format
151fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana    private static final int ACCOUNTS_VERSION = 2;
152fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
153fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana    private static HashMap<String, String> sAuthorityRenames;
154fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
155fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana    static {
156fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        sAuthorityRenames = new HashMap<String, String>();
157fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        sAuthorityRenames.put("contacts", "com.android.contacts");
158fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        sAuthorityRenames.put("calendar", "com.android.calendar");
159fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana    }
160c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana
161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class PendingOperation {
1628ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        final EndPoint target;
16357286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        final int reason;
164231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int syncSource;
165231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final Bundle extras;        // note: read-only.
166307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        final boolean expedited;
167360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
16856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        final int authorityId;
16956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        // No longer used.
17056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        // Keep around for sake up updating from pending.bin to pending.xml
171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        byte[] flatExtras;
172360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
17356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        PendingOperation(AuthorityInfo authority, int reason, int source,
17456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                 Bundle extras, boolean expedited) {
1758ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            this.target = authority.target;
176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = source;
17757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            this.reason = reason;
178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = extras != null ? new Bundle(extras) : extras;
179307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            this.expedited = expedited;
18056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.authorityId = authority.ident;
181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
183231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        PendingOperation(PendingOperation other) {
18457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            this.reason = other.reason;
185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.syncSource = other.syncSource;
1868ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            this.target = other.target;
187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.extras = other.extras;
188231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.authorityId = other.authorityId;
189307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            this.expedited = other.expedited;
19056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
19156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
19256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        /**
1938ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         * Considered equal if they target the same sync adapter (A
1948ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         * {@link android.content.SyncService}
19556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams         * is considered an adapter), for the same userId.
19656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams         * @param other PendingOperation to compare.
19756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams         * @return true if the two pending ops are the same.
19856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams         */
19956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        public boolean equals(PendingOperation other) {
2008ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            return target.matchesSpec(other.target);
20156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
20256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
20356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        public String toString() {
2048ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            return "service=" + target.service
2058ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        + " user=" + target.userId
2068ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        + " auth=" + target
2078ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        + " account=" + target.account
20856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        + " src=" + syncSource
20956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        + " extras=" + extras;
210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
212360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static class AccountInfo {
21404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        final AccountAndUser accountAndUser;
215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final HashMap<String, AuthorityInfo> authorities =
216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                new HashMap<String, AuthorityInfo>();
217360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
21804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        AccountInfo(AccountAndUser accountAndUser) {
21904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            this.accountAndUser = accountAndUser;
220231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
221231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
222360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
22356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /**  Bare bones representation of a sync target. */
22456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static class EndPoint {
22556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        public final static EndPoint USER_ALL_PROVIDER_ALL_ACCOUNTS_ALL =
22656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                new EndPoint(null, null, UserHandle.USER_ALL);
227fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        final ComponentName service;
2287a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn        final Account account;
22904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        final int userId;
23056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        final String provider;
23156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        final boolean target_service;
23256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        final boolean target_provider;
23356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
23456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        public EndPoint(ComponentName service, int userId) {
23556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.service = service;
23656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.userId = userId;
23756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.account = null;
23856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.provider = null;
23956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.target_service = true;
24056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.target_provider = false;
24156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
24256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
24356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        public EndPoint(Account account, String provider, int userId) {
24456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.account = account;
24556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.provider = provider;
24656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.userId = userId;
24756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.service = null;
24856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.target_service = false;
24956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            this.target_provider = true;
25056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
25156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
25256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        /**
2538ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         * An Endpoint for a sync matches if it targets the same sync adapter for the same user.
2548ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         *
2558ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         * @param spec the Endpoint to match. If the spec has null fields, they indicate a wildcard
2568ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         * and match any.
25756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams         */
2588ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        public boolean matchesSpec(EndPoint spec) {
2598ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            if (userId != spec.userId
26056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    && userId != UserHandle.USER_ALL
2618ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    && spec.userId != UserHandle.USER_ALL) {
26256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                return false;
26356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
2648ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            if (target_service && spec.target_service) {
2658ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                return service.equals(spec.service);
2668ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            } else if (target_provider && spec.target_provider) {
26756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                boolean accountsMatch;
2688ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                if (spec.account == null) {
26956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    accountsMatch = true;
27056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                } else {
2718ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    accountsMatch = account.equals(spec.account);
27256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
27356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                boolean providersMatch;
2748ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                if (spec.provider == null) {
27556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    providersMatch = true;
27656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                } else {
2778ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    providersMatch = provider.equals(spec.provider);
27856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
27956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                return accountsMatch && providersMatch;
28056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
28156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return false;
28256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
28356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
28456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        public String toString() {
28556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            StringBuilder sb = new StringBuilder();
28656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (target_provider) {
28756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                sb.append(account == null ? "ALL ACCS" : account.name)
28856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    .append("/")
28956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    .append(provider == null ? "ALL PDRS" : provider);
29056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            } else if (target_service) {
2918ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                sb.append(service.getPackageName() + "/")
2928ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                  .append(service.getClassName());
29356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            } else {
29456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                sb.append("invalid target");
29556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
2968ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            sb.append(":u" + userId);
29756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return sb.toString();
29856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
29956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
30056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
30156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public static class AuthorityInfo {
3028ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        final EndPoint target;
303231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int ident;
304231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean enabled;
3055e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        int syncable;
30656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        /** Time at which this sync will run, taking into account backoff. */
307307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        long backoffTime;
30856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        /** Amount of delay due to backoff. */
309307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        long backoffDelay;
3108ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        /** Time offset to add to any requests coming to this target. */
311307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        long delayUntil;
31256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
313fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        final ArrayList<PeriodicSync> periodicSyncs;
314ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
3153aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia        /**
3163aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia         * Copy constructor for making deep-ish copies. Only the bundles stored
3173aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia         * in periodic syncs can make unexpected changes.
3183aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia         *
3193aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia         * @param toCopy AuthorityInfo to be copied.
3203aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia         */
3213aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia        AuthorityInfo(AuthorityInfo toCopy) {
3228ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            target = toCopy.target;
3233aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia            ident = toCopy.ident;
3243aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia            enabled = toCopy.enabled;
3253aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia            syncable = toCopy.syncable;
3263aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia            backoffTime = toCopy.backoffTime;
3273aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia            backoffDelay = toCopy.backoffDelay;
3283aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia            delayUntil = toCopy.delayUntil;
329fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            periodicSyncs = new ArrayList<PeriodicSync>();
330fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            for (PeriodicSync sync : toCopy.periodicSyncs) {
3313aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia                // Still not a perfect copy, because we are just copying the mappings.
332fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                periodicSyncs.add(new PeriodicSync(sync));
3333aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia            }
3343aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia        }
3353aca7d7bec4b48bc68480b9d6b0ccdabf6903dfbCarlos Valdivia
33656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        AuthorityInfo(EndPoint info, int id) {
3378ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            target = info;
33856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            ident = id;
33956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            enabled = info.target_provider ?
34056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    SYNC_ENABLED_DEFAULT : true;
34156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            // Service is active by default,
34256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (info.target_service) {
34356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                this.syncable = 1;
34456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
34556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            periodicSyncs = new ArrayList<PeriodicSync>();
34656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            defaultInitialisation();
34756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
34856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
34956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        private void defaultInitialisation() {
3504a6679b97e0285c5b65ec5c0d9080ff90d3e9e81Fred Quintana            syncable = -1; // default to "unknown"
351307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            backoffTime = -1; // if < 0 then we aren't in backoff mode
352307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            backoffDelay = -1; // if < 0 then we aren't in backoff mode
35356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            PeriodicSync defaultSync;
35456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            // Old version is one sync a day. Empty bundle gets replaced by any addPeriodicSync()
35556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            // call.
3568ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            if (target.target_provider) {
35756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                defaultSync =
3588ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        new PeriodicSync(target.account, target.provider,
35956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            new Bundle(),
36056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            DEFAULT_POLL_FREQUENCY_SECONDS,
36156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            calculateDefaultFlexTime(DEFAULT_POLL_FREQUENCY_SECONDS));
36256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                periodicSyncs.add(defaultSync);
36356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
36506485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams
36606485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams        @Override
36706485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams        public String toString() {
36806485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams            return target + ", enabled=" + enabled + ", syncable=" + syncable + ", backoff="
36906485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams                    + backoffTime + ", delay=" + delayUntil;
37006485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams        }
371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
372360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class SyncHistoryItem {
374231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int authorityId;
375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int historyId;
376231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long eventTime;
377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long elapsedTime;
378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int source;
379231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        int event;
380231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long upstreamActivity;
381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long downstreamActivity;
382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String mesg;
383dc47556cb37b6f25faceb5eb97cef60d384b55fbFred Quintana        boolean initialization;
38457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        Bundle extras;
38557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert        int reason;
386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
387360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static class DayStats {
389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public final int day;
390231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int successCount;
391231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long successTime;
392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public int failureCount;
393231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public long failureTime;
394360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
395231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        public DayStats(int day) {
396231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            this.day = day;
397231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
398231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
399360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
40004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    interface OnSyncRequestListener {
40156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
40256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        /** Called when a sync is needed on an account(s) due to some change in state. */
40356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        public void onSyncRequest(EndPoint info, int reason, Bundle extras);
40404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
40504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
406231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // Primary list of all syncable authorities.  Also our global lock.
407231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<AuthorityInfo> mAuthorities =
408231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<AuthorityInfo>();
409360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
41004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private final HashMap<AccountAndUser, AccountInfo> mAccounts
41104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            = new HashMap<AccountAndUser, AccountInfo>();
412231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn
413231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<PendingOperation> mPendingOperations =
414231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<PendingOperation>();
415360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
41604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private final SparseArray<ArrayList<SyncInfo>> mCurrentSyncs
41704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            = new SparseArray<ArrayList<SyncInfo>>();
418360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
419231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final SparseArray<SyncStatusInfo> mSyncStatus =
420231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new SparseArray<SyncStatusInfo>();
421360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
422231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final ArrayList<SyncHistoryItem> mSyncHistory =
423231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            new ArrayList<SyncHistoryItem>();
424360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
425231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final RemoteCallbackList<ISyncStatusObserver> mChangeListeners
426231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            = new RemoteCallbackList<ISyncStatusObserver>();
427360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
4288ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams    /** Reverse mapping for component name -> <userid -> target id>. */
42956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    private final ArrayMap<ComponentName, SparseArray<AuthorityInfo>> mServices =
43056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            new ArrayMap<ComponentName, SparseArray<AuthorityInfo>>();
431fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
43277c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana    private int mNextAuthorityId = 0;
43377c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana
434231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    // We keep 4 weeks of stats.
435231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final DayStats[] mDayStats = new DayStats[7*4];
436231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Calendar mCal;
437231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYear;
438231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mYearInDays;
439360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
440231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final Context mContext;
441c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
442231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static volatile SyncStorageEngine sSyncStorageEngine = null;
443360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
44469d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma    private int mSyncRandomOffset;
44569d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma
446231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
447231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the core engine state: all accounts and the
448231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * settings for them.  It must never be lost, and should be changed
449231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * infrequently, so it is stored as an XML file.
450231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
451231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mAccountInfoFile;
452360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
453231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
454231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the current sync status.  We would like to retain
455231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * it across boots, but its loss is not the end of the world, so we store
456231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * this information as binary data.
457231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
458231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatusFile;
459360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
460231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
461231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains sync statistics.  This is purely debugging information
462231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so is written infrequently and can be thrown away at any time.
463231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
464231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mStatisticsFile;
465360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
466231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
467231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * This file contains the pending sync operations.  It is a binary file,
468231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * which must be updated every time an operation is added or removed,
469231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so we have special handling of it.
470231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
471231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private final AtomicFile mPendingFile;
472231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private static final int PENDING_FINISH_TO_WRITE = 4;
473231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNumPendingFinished = 0;
474360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
475231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private int mNextHistoryId = 0;
47604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private SparseArray<Boolean> mMasterSyncAutomatically = new SparseArray<Boolean>();
4772b5d0ea5e90bd5b9a1b3afdd230e8907315e65e2Yameng Huang    private boolean mDefaultMasterSyncAutomatically;
47804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
47904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private OnSyncRequestListener mSyncRequestListener;
480360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
481c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    private SyncStorageEngine(Context context, File dataDir) {
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sSyncStorageEngine = this;
484360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
485231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
486360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
4872b5d0ea5e90bd5b9a1b3afdd230e8907315e65e2Yameng Huang        mDefaultMasterSyncAutomatically = mContext.getResources().getBoolean(
4882b5d0ea5e90bd5b9a1b3afdd230e8907315e65e2Yameng Huang               com.android.internal.R.bool.config_syncstorageengine_masterSyncAutomatically);
4892b5d0ea5e90bd5b9a1b3afdd230e8907315e65e2Yameng Huang
490231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File systemDir = new File(dataDir, "system");
491231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File syncDir = new File(systemDir, "sync");
492c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        syncDir.mkdirs();
493ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams
494ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        maybeDeleteLegacyPendingInfoLocked(syncDir);
495ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams
496231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
497231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
498ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        mPendingFile = new AtomicFile(new File(syncDir, "pending.xml"));
499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
500360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
501231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readAccountInfoLocked();
502231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatusLocked();
503231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readPendingOperationsLocked();
504231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        readStatisticsLocked();
50577c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        readAndDeleteLegacyAccountInfoLocked();
50677c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        writeAccountInfoLocked();
50777c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        writeStatusLocked();
50877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        writePendingOperationsLocked();
50977c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        writeStatisticsLocked();
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine newTestInstance(Context context) {
513c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return new SyncStorageEngine(context, context.getFilesDir());
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void init(Context context) {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine != null) {
518307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            return;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
520c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        // This call will return the correct directory whether Encrypted File Systems is
521c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        // enabled or not.
522a3cdaa5337fa573c4c61770195d6232c2e587090Jason parks        File dataDir = Environment.getSecureDataDirectory();
523c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        sSyncStorageEngine = new SyncStorageEngine(context, dataDir);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static SyncStorageEngine getSingleton() {
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sSyncStorageEngine == null) {
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("not initialized");
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sSyncStorageEngine;
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
53304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected void setOnSyncRequestListener(OnSyncRequestListener listener) {
53404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        if (mSyncRequestListener == null) {
53504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            mSyncRequestListener = listener;
53604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
53704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
53804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
539231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    @Override public void handleMessage(Message msg) {
540231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (msg.what == MSG_WRITE_STATUS) {
5414e80820ab54f3985220ff06b2fcd381565e9f19dDianne Hackborn            synchronized (mAuthorities) {
542231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
543231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
544231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } else if (msg.what == MSG_WRITE_STATISTICS) {
5454e80820ab54f3985220ff06b2fcd381565e9f19dDianne Hackborn            synchronized (mAuthorities) {
546231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
550360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
55169d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma    public int getSyncRandomOffset() {
55269d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma        return mSyncRandomOffset;
55369d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma    }
55469d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma
555231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
556231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
557231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.register(callback, mask);
558231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
559231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
560360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void removeStatusChangeListener(ISyncStatusObserver callback) {
562231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mChangeListeners.unregister(callback);
564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
566360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
567fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
568fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * Figure out a reasonable flex time for cases where none is provided (old api calls).
569fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * @param syncTimeSeconds requested sync time from now.
570fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * @return amount of seconds before syncTimeSeconds that the sync can occur.
571fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     *      I.e.
572fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     *      earliest_sync_time = syncTimeSeconds - calculateDefaultFlexTime(syncTimeSeconds)
57356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * The flex time is capped at a percentage of the {@link #DEFAULT_POLL_FREQUENCY_SECONDS}.
574fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
575fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    public static long calculateDefaultFlexTime(long syncTimeSeconds) {
576fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        if (syncTimeSeconds < DEFAULT_MIN_FLEX_ALLOWED_SECS) {
577fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            // Small enough sync request time that we don't add flex time - developer probably
578fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            // wants to wait for an operation to occur before syncing so we honour the
579fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            // request time.
580fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            return 0L;
581fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        } else if (syncTimeSeconds < DEFAULT_POLL_FREQUENCY_SECONDS) {
582fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            return (long) (syncTimeSeconds * DEFAULT_FLEX_PERCENT_SYNC);
583fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        } else {
584fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            // Large enough sync request time that we cap the flex time.
585fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            return (long) (DEFAULT_POLL_FREQUENCY_SECONDS * DEFAULT_FLEX_PERCENT_SYNC);
586fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        }
587fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    }
588fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
589231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void reportChange(int which) {
590231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        ArrayList<ISyncStatusObserver> reports = null;
591231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
592231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mChangeListeners.beginBroadcast();
593231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
594231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
595231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Integer mask = (Integer)mChangeListeners.getBroadcastCookie(i);
596231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if ((which & mask.intValue()) == 0) {
597231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
598231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
599231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (reports == null) {
600231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports = new ArrayList<ISyncStatusObserver>(i);
601231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
602231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                reports.add(mChangeListeners.getBroadcastItem(i));
603231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
604b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0Dianne Hackborn            mChangeListeners.finishBroadcast();
605231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
606360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
60756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (Log.isLoggable(TAG, Log.VERBOSE)) {
60877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            Log.v(TAG, "reportChange " + which + " to: " + reports);
60977c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        }
610360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
611231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (reports != null) {
612231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = reports.size();
613231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
614231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
615231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
616231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    reports.get(i).onStatusChanged(which);
617231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (RemoteException e) {
618231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // The remote callback list will take care of this for us.
619231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
620231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
621231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
622231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
62370c874ba20b586712a7550b6c5efeb6dc0fdf9faAmith Yamasani
62404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public boolean getSyncAutomatically(Account account, int userId, String providerName) {
625231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
626231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (account != null) {
62756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                AuthorityInfo authority = getAuthorityLocked(
62856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        new EndPoint(account, providerName, userId),
629ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        "getSyncAutomatically");
630ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                return authority != null && authority.enabled;
631231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
632ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana
633231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mAuthorities.size();
634231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
635231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
63656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                AuthorityInfo authorityInfo = mAuthorities.valueAt(i);
6378ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                if (authorityInfo.target.matchesSpec(new EndPoint(account, providerName, userId))
63856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        && authorityInfo.enabled) {
639231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
640231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
642231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
64604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public void setSyncAutomatically(Account account, int userId, String providerName,
64704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            boolean sync) {
64856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (Log.isLoggable(TAG, Log.VERBOSE)) {
64940e9f2922cae76ffcbc521481e5be8e80e8744efDianne Hackborn            Log.d(TAG, "setSyncAutomatically: " + /* account + */" provider " + providerName
65040e9f2922cae76ffcbc521481e5be8e80e8744efDianne Hackborn                    + ", user " + userId + " -> " + sync);
65140e9f2922cae76ffcbc521481e5be8e80e8744efDianne Hackborn        }
652231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
65356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authority =
65456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    getOrCreateAuthorityLocked(
65556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            new EndPoint(account, providerName, userId),
65656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            -1 /* ident */,
65756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            false);
65877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            if (authority.enabled == sync) {
65956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (Log.isLoggable(TAG, Log.VERBOSE)) {
66040e9f2922cae76ffcbc521481e5be8e80e8744efDianne Hackborn                    Log.d(TAG, "setSyncAutomatically: already set to " + sync + ", doing nothing");
66140e9f2922cae76ffcbc521481e5be8e80e8744efDianne Hackborn                }
66277c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                return;
66377c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            }
6648294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato            authority.enabled = sync;
665231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6678294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato
66877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        if (sync) {
66957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            requestSync(account, userId, SyncOperation.REASON_SYNC_AUTO, providerName,
67057286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                    new Bundle());
6718294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        }
672ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
67504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public int getIsSyncable(Account account, int userId, String providerName) {
6765e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        synchronized (mAuthorities) {
6775e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            if (account != null) {
67856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                AuthorityInfo authority = getAuthorityLocked(
67956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        new EndPoint(account, providerName, userId),
68056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        "get authority syncable");
6815e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                if (authority == null) {
6825e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    return -1;
6835e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
6845e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                return authority.syncable;
6855e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
6865e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
6875e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            int i = mAuthorities.size();
6885e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            while (i > 0) {
6895e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                i--;
69056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                AuthorityInfo authorityInfo = mAuthorities.valueAt(i);
6918ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                if (authorityInfo.target != null
6928ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        && authorityInfo.target.provider.equals(providerName)) {
69356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    return authorityInfo.syncable;
6945e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
6955e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            }
6965e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana            return -1;
6975e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
6985e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
6995e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
70004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public void setIsSyncable(Account account, int userId, String providerName, int syncable) {
7018ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        setSyncableStateForEndPoint(new EndPoint(account, providerName, userId), syncable);
70256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
70356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
7047a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams    public boolean getIsTargetServiceActive(ComponentName cname, int userId) {
70556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        synchronized (mAuthorities) {
70656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (cname != null) {
70756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                AuthorityInfo authority = getAuthorityLocked(
70856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        new EndPoint(cname, userId),
7098ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        "get service active");
71056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (authority == null) {
7117a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams                    return false;
71256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
7137a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams                return (authority.syncable == 1);
71456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
7157a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams            return false;
71656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
71756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
71856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
7197a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams    public void setIsTargetServiceActive(ComponentName cname, int userId, boolean active) {
7208ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        setSyncableStateForEndPoint(new EndPoint(cname, userId), active ? 1 : 0);
72156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
72256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
72356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /**
72456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * An enabled sync service and a syncable provider's adapter both get resolved to the same
72556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * persisted variable - namely the "syncable" attribute for an AuthorityInfo in accounts.xml.
7267a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams     * @param target target to set value for.
7277a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams     * @param syncable 0 indicates unsyncable, <0 unknown, >0 is active/syncable.
72856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     */
7298ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams    private void setSyncableStateForEndPoint(EndPoint target, int syncable) {
7307a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams        AuthorityInfo aInfo;
7317a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams        synchronized (mAuthorities) {
7327a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams            aInfo = getOrCreateAuthorityLocked(target, -1, false);
7337a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams            if (syncable > 1) {
7347a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams                syncable = 1;
7357a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams            } else if (syncable < -1) {
7367a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams                syncable = -1;
7377a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams            }
73856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (Log.isLoggable(TAG, Log.VERBOSE)) {
7397a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams                Log.d(TAG, "setIsSyncable: " + aInfo.toString() + " -> " + syncable);
74077c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            }
7417a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams            if (aInfo.syncable == syncable) {
7427a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams                if (Log.isLoggable(TAG, Log.VERBOSE)) {
7437a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams                    Log.d(TAG, "setIsSyncable: already set to " + syncable + ", doing nothing");
7447a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams                }
7457a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams                return;
7467a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams            }
7477a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams            aInfo.syncable = syncable;
7487a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams            writeAccountInfoLocked();
7495e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
75077c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        if (syncable > 0) {
75156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            requestSync(aInfo, SyncOperation.REASON_IS_SYNCABLE, new Bundle());
7525e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        }
7535e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
7545e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana    }
7555e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana
75656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public Pair<Long, Long> getBackoff(EndPoint info) {
757307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
75856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authority = getAuthorityLocked(info, "getBackoff");
75956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (authority != null) {
76056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                return Pair.create(authority.backoffTime, authority.backoffDelay);
761307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
76256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return null;
763307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
764307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
765307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
76656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /**
76756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * Update the backoff for the given endpoint. The endpoint may be for a provider/account and
76856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * the account or provider info be null, which signifies all accounts or providers.
76956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     */
77056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public void setBackoff(EndPoint info, long nextSyncTime, long nextDelay) {
77156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (Log.isLoggable(TAG, Log.VERBOSE)) {
77256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            Log.v(TAG, "setBackoff: " + info
773307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                    + " -> nextSyncTime " + nextSyncTime + ", nextDelay " + nextDelay);
774307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
77556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        boolean changed;
776307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
77756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (info.target_provider
77856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    && (info.account == null || info.provider == null)) {
77956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                // Do more work for a provider sync if the provided info has specified all
78056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                // accounts/providers.
78156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                changed = setBackoffLocked(
78256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        info.account /* may be null */,
78356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        info.userId,
78456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        info.provider /* may be null */,
78556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        nextSyncTime, nextDelay);
786307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            } else {
78756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                AuthorityInfo authorityInfo =
78856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        getOrCreateAuthorityLocked(info, -1 /* ident */, true);
78956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (authorityInfo.backoffTime == nextSyncTime
79056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        && authorityInfo.backoffDelay == nextDelay) {
79156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    changed = false;
79256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                } else {
79356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    authorityInfo.backoffTime = nextSyncTime;
79456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    authorityInfo.backoffDelay = nextDelay;
79556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    changed = true;
796307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana                }
797307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
798307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
799307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        if (changed) {
800307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
801307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
802307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
803307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
80456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /**
80556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * Either set backoff for a specific authority, or set backoff for all the
80656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * accounts on a specific adapter/all adapters.
80756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     *
80856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * @param account account for which to set backoff. Null to specify all accounts.
80956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * @param userId id of the user making this request.
81056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * @param providerName provider for which to set backoff. Null to specify all providers.
8117a2ab3a060f89c5de7f44f85bf58a7b6f6884873Matthew Williams     * @return true if a change occured.
81256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     */
81356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    private boolean setBackoffLocked(Account account, int userId, String providerName,
81456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            long nextSyncTime, long nextDelay) {
81556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        boolean changed = false;
81656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        for (AccountInfo accountInfo : mAccounts.values()) {
81756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (account != null && !account.equals(accountInfo.accountAndUser.account)
81856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    && userId != accountInfo.accountAndUser.userId) {
81956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                continue;
82056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
82156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
82256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (providerName != null
8238ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        && !providerName.equals(authorityInfo.target.provider)) {
82456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    continue;
82556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
82656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (authorityInfo.backoffTime != nextSyncTime
82756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        || authorityInfo.backoffDelay != nextDelay) {
82856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    authorityInfo.backoffTime = nextSyncTime;
82956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    authorityInfo.backoffDelay = nextDelay;
83056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    changed = true;
83156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
83256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
83356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
83456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        return changed;
83556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
83656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
837119aac93f8d757ff464dd4d1135ffcf37f7cda02Matthew Williams    public void clearAllBackoffsLocked(SyncQueue syncQueue) {
838744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert        boolean changed = false;
839744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert        synchronized (mAuthorities) {
84056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                // Clear backoff for all sync adapters.
841a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                for (AccountInfo accountInfo : mAccounts.values()) {
842a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                    for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
843a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                        if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
844a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                                || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
84556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
846119aac93f8d757ff464dd4d1135ffcf37f7cda02Matthew Williams                                Log.v(TAG, "clearAllBackoffsLocked:"
8478ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                        + " authority:" + authorityInfo.target
848a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                                        + " account:" + accountInfo.accountAndUser.account.name
849a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                                        + " user:" + accountInfo.accountAndUser.userId
850a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                                        + " backoffTime was: " + authorityInfo.backoffTime
851a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                                        + " backoffDelay was: " + authorityInfo.backoffDelay);
852a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                            }
853a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                            authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
854a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                            authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
855a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey                            changed = true;
856744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert                        }
857744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert                    }
858744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert                }
85956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                // Clear backoff for all sync services.
86056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                for (ComponentName service : mServices.keySet()) {
86156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    SparseArray<AuthorityInfo> aInfos = mServices.get(service);
86256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    for (int i = 0; i < aInfos.size(); i++) {
86356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        AuthorityInfo authorityInfo = aInfos.valueAt(i);
86456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
86556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
86656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
86756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
86856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        }
86956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    }
87056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                syncQueue.clearBackoffs();
871744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert            }
872744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert        }
873744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert
874744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert        if (changed) {
875744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert            reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
876744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert        }
877744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert    }
878744e310f6635026396e32ab0a2c009e464c2be3cAlon Albert
87956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public long getDelayUntilTime(EndPoint info) {
880307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
88156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authority = getAuthorityLocked(info, "getDelayUntil");
88256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (authority == null) {
88356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                return 0;
884307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
88556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return authority.delayUntil;
886307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
887307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
888307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
88956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public void setDelayUntilTime(EndPoint info, long delayUntil) {
89056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (Log.isLoggable(TAG, Log.VERBOSE)) {
89156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            Log.v(TAG, "setDelayUntil: " + info
89256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    + " -> delayUntil " + delayUntil);
89356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
894307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        synchronized (mAuthorities) {
89556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authority = getOrCreateAuthorityLocked(info, -1, true);
89656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (authority.delayUntil == delayUntil) {
89756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                return;
898307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana            }
89956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            authority.delayUntil = delayUntil;
900307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana        }
90156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
902307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana    }
903307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
90456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public void updateOrAddPeriodicSync(EndPoint info, long period, long flextime, Bundle extras) {
90556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (Log.isLoggable(TAG, Log.VERBOSE)) {
90656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            Log.v(TAG, "addPeriodicSync: " + info
90756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    + " -> period " + period + ", flex " + flextime + ", extras "
90856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    + extras.toString());
909c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
910c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
91156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (period <= 0) {
91256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                Log.e(TAG, "period < 0, should never happen in updateOrAddPeriodicSync");
913fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            }
91456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (extras == null) {
91556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                Log.e(TAG, "null extras, should never happen in updateOrAddPeriodicSync:");
916fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            }
91777c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            try {
91856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                PeriodicSync toUpdate;
91956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (info.target_provider) {
92056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    toUpdate = new PeriodicSync(info.account,
92156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            info.provider,
92256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            extras,
92356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            period,
92456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            flextime);
92556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                } else {
9265a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams                    return;
92756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
92877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                AuthorityInfo authority =
92956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        getOrCreateAuthorityLocked(info, -1, false);
93056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                // add this periodic sync if an equivalent periodic doesn't already exist.
93156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                boolean alreadyPresent = false;
93256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                for (int i = 0, N = authority.periodicSyncs.size(); i < N; i++) {
93356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    PeriodicSync syncInfo = authority.periodicSyncs.get(i);
93456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    if (SyncManager.syncExtrasEquals(syncInfo.extras,
93556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            extras,
93656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            true /* includeSyncSettings*/)) {
93756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        if (period == syncInfo.period &&
93856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                flextime == syncInfo.flexTime) {
93956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            // Absolutely the same.
94056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            return;
941c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        }
94256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        authority.periodicSyncs.set(i, toUpdate);
94356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        alreadyPresent = true;
94456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        break;
945c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    }
94656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
94756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                // If we added an entry to the periodicSyncs array also add an entry to
94856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                // the periodic syncs status to correspond to it.
94956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (!alreadyPresent) {
95056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    authority.periodicSyncs.add(toUpdate);
95156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
95256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    // A new periodic sync is initialised as already having been run.
95356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    status.setPeriodicSyncTime(
95456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            authority.periodicSyncs.size() - 1,
95556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            System.currentTimeMillis());
95656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
95756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            } finally {
95856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                writeAccountInfoLocked();
95956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                writeStatusLocked();
96056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
96156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
96256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
96356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
96456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
96556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public void removePeriodicSync(EndPoint info, Bundle extras) {
96656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        synchronized(mAuthorities) {
96756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            try {
96856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                AuthorityInfo authority =
96956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        getOrCreateAuthorityLocked(info, -1, false);
9708ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                // Remove any periodic syncs that match the target and extras.
97156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                SyncStatusInfo status = mSyncStatus.get(authority.ident);
97256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                boolean changed = false;
97356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                Iterator<PeriodicSync> iterator = authority.periodicSyncs.iterator();
97456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                int i = 0;
97556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                while (iterator.hasNext()) {
97656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    PeriodicSync syncInfo = iterator.next();
97756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    if (SyncManager.syncExtrasEquals(syncInfo.extras,
97856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            extras,
97956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            true /* includeSyncSettings */)) {
98056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        iterator.remove();
98156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        changed = true;
98256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        // If we removed an entry from the periodicSyncs array also
98356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        // remove the corresponding entry from the status
98456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        if (status != null) {
98556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            status.removePeriodicSyncTime(i);
98677c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                        } else {
98756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            Log.e(TAG, "Tried removing sync status on remove periodic sync but"
98856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                    + " did not find it.");
989c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        }
99056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    } else {
99156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        i++;
99277c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                    }
99356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
99456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (!changed) {
99556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    return;
996c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
99777c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            } finally {
99877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                writeAccountInfoLocked();
99977c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                writeStatusLocked();
1000c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1001c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1002c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
1003c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1004c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
100556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /**
10068ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * @return list of periodic syncs for a target. Never null. If no such syncs exist, returns an
10078ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * empty list.
100856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     */
100956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public List<PeriodicSync> getPeriodicSyncs(EndPoint info) {
1010c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
101156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authorityInfo = getAuthorityLocked(info, "getPeriodicSyncs");
101256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            ArrayList<PeriodicSync> syncs = new ArrayList<PeriodicSync>();
101356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (authorityInfo != null) {
101456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                for (PeriodicSync item : authorityInfo.periodicSyncs) {
1015fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    // Copy and send out. Necessary for thread-safety although it's parceled.
1016fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    syncs.add(new PeriodicSync(item));
1017c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
1018c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
101956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return syncs;
1020c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1021c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1022c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
102304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public void setMasterSyncAutomatically(boolean flag, int userId) {
1024231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
102504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Boolean auto = mMasterSyncAutomatically.get(userId);
10268ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            if (auto != null && auto.equals(flag)) {
102777c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                return;
102877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            }
102904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            mMasterSyncAutomatically.put(userId, flag);
1030231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            writeAccountInfoLocked();
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
103277c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        if (flag) {
103357286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            requestSync(null, userId, SyncOperation.REASON_MASTER_SYNC_AUTO, null,
103457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert                    new Bundle());
10358294fadb155a33da8a40d8412afb35e6b424afcbJoe Onorato        }
1036ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
10377a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey        mContext.sendBroadcast(ContentResolver.ACTION_SYNC_CONN_STATUS_CHANGED);
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
104004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public boolean getMasterSyncAutomatically(int userId) {
1041231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
104204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Boolean auto = mMasterSyncAutomatically.get(userId);
10432b5d0ea5e90bd5b9a1b3afdd230e8907315e65e2Yameng Huang            return auto == null ? mDefaultMasterSyncAutomatically : auto;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1046360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1047231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public AuthorityInfo getAuthority(int authorityId) {
1048231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1049231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mAuthorities.get(authorityId);
1050231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1051231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1052360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
105456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * Returns true if there is currently a sync operation being actively processed for the given
10558ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * target.
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
105756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public boolean isSyncActive(EndPoint info) {
1058231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
105956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            for (SyncInfo syncInfo : getCurrentSyncs(info.userId)) {
1060918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana                AuthorityInfo ainfo = getAuthority(syncInfo.authorityId);
10618ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                if (ainfo != null && ainfo.target.matchesSpec(info)) {
1062231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
1063231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1064231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1066231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return false;
1067231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1068360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
106956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public PendingOperation insertIntoPending(SyncOperation op) {
107056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        PendingOperation pop;
1071231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
107256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (Log.isLoggable(TAG, Log.VERBOSE)) {
107356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                Log.v(TAG, "insertIntoPending: authority=" + op.target
107404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        + " extras=" + op.extras);
107577c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            }
107656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            final EndPoint info = op.target;
107756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authority =
107856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    getOrCreateAuthorityLocked(info,
107956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            -1 /* desired identifier */,
108056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            true /* write accounts to storage */);
1081231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
1082231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return null;
1083231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1084360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
108556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            pop = new PendingOperation(authority, op.reason, op.syncSource, op.extras,
10866428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams                    op.isExpedited());
108756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            mPendingOperations.add(pop);
108806485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams            appendPendingOperationLocked(pop);
1089360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1090231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
1091231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.pending = true;
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1093ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
109456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        return pop;
1095231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1097fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
1098fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * Remove from list of pending operations. If successful, search through list for matching
10998ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * authorities. If there are no more pending syncs for the same target,
11008ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * update the SyncStatusInfo for that target.
110156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * @param op Pending op to delete.
1102fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
1103231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public boolean deleteFromPending(PendingOperation op) {
1104231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        boolean res = false;
1105231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
110656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (Log.isLoggable(TAG, Log.VERBOSE)) {
110756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                Log.v(TAG, "deleteFromPending: account=" + op.toString());
110877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            }
1109231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mPendingOperations.remove(op)) {
1110231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (mPendingOperations.size() == 0
1111231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || mNumPendingFinished >= PENDING_FINISH_TO_WRITE) {
1112231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writePendingOperationsLocked();
1113231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished = 0;
1114231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
1115231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mNumPendingFinished++;
1116231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
11178ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                AuthorityInfo authority = getAuthorityLocked(op.target, "deleteFromPending");
1118231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
111956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
112056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        Log.v(TAG, "removing - " + authority.toString());
112156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    }
1122231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    final int N = mPendingOperations.size();
1123231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean morePending = false;
112456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    for (int i = 0; i < N; i++) {
1125231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        PendingOperation cur = mPendingOperations.get(i);
112656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        if (cur.equals(op)) {
1127231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            morePending = true;
1128231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
1129231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1130231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1131360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1132231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!morePending) {
113356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "no more pending!");
1134231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
1135231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
1136231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1137231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1138231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                res = true;
1139231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1140231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1141360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1142ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
1143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return res;
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1147231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return a copy of the current array of pending operations.  The
1148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * PendingOperation objects are the real objects stored inside, so that
1149231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * they can be used with deleteFromPending().
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1151231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<PendingOperation> getPendingOperations() {
1152231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1153231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return new ArrayList<PendingOperation>(mPendingOperations);
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1156360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1158231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return the number of currently pending operations.
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1160231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public int getPendingOperationCount() {
1161231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1162231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return mPendingOperations.size();
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1165360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1167231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Called when the set of account has changed, given the new array of
1168231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * active accounts.
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
117004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public void doDatabaseCleanup(Account[] accounts, int userId) {
1171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
11728ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            if (Log.isLoggable(TAG, Log.VERBOSE)) {
11738ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                Log.v(TAG, "Updating for new accounts...");
11748ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            }
1175231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SparseArray<AuthorityInfo> removing = new SparseArray<AuthorityInfo>();
1176231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Iterator<AccountInfo> accIt = mAccounts.values().iterator();
1177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (accIt.hasNext()) {
1178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AccountInfo acc = accIt.next();
117904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                if (!ArrayUtils.contains(accounts, acc.accountAndUser.account)
118004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        && acc.accountAndUser.userId == userId) {
1181231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // This account no longer exists...
118256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
118340e9f2922cae76ffcbc521481e5be8e80e8744efDianne Hackborn                        Log.v(TAG, "Account removed: " + acc.accountAndUser);
118477c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                    }
1185231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    for (AuthorityInfo auth : acc.authorities.values()) {
1186231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        removing.put(auth.ident, auth);
1187231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1188231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    accIt.remove();
1189231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1190231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1191360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1192231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Clean out all data structures.
1193231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = removing.size();
1194231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (i > 0) {
1195231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                while (i > 0) {
1196231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    i--;
1197231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int ident = removing.keyAt(i);
1198231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    mAuthorities.remove(ident);
1199231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int j = mSyncStatus.size();
1200231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
1201231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
1202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncStatus.keyAt(j) == ident) {
1203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncStatus.remove(mSyncStatus.keyAt(j));
1204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1206231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    j = mSyncHistory.size();
1207231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (j > 0) {
1208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        j--;
1209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (mSyncHistory.get(j).authorityId == ident) {
1210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            mSyncHistory.remove(j);
1211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1212231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1214231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeAccountInfoLocked();
1215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
1216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writePendingOperationsLocked();
1217231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
1218231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1222231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1223918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana     * Called when a sync is starting. Supply a valid ActiveSyncContext with information
1224918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana     * about the sync.
1225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1226918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    public SyncInfo addActiveSync(SyncManager.ActiveSyncContext activeSyncContext) {
1227918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        final SyncInfo syncInfo;
1228231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
122956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1230918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana                Log.v(TAG, "setActiveSync: account="
123156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    + " auth=" + activeSyncContext.mSyncOperation.target
1232918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana                    + " src=" + activeSyncContext.mSyncOperation.syncSource
1233918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana                    + " extras=" + activeSyncContext.mSyncOperation.extras);
1234918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana            }
123556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            final EndPoint info = activeSyncContext.mSyncOperation.target;
123656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authorityInfo = getOrCreateAuthorityLocked(
123756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    info,
12388ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    -1 /* assign a new identifier if creating a new target */,
1239918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana                    true /* write to storage if this results in a change */);
124056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            syncInfo = new SyncInfo(
124156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    authorityInfo.ident,
12428ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    authorityInfo.target.account,
12438ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    authorityInfo.target.provider,
1244918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana                    activeSyncContext.mStartTime);
12458ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            getCurrentSyncs(authorityInfo.target.userId).add(syncInfo);
1246918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        }
1247918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        reportActiveChange();
1248918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        return syncInfo;
1249918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    }
1250918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana
1251918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana    /**
1252918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana     * Called to indicate that a previously active sync is no longer active.
1253918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana     */
125404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public void removeActiveSync(SyncInfo syncInfo, int userId) {
1255918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        synchronized (mAuthorities) {
125656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (Log.isLoggable(TAG, Log.VERBOSE)) {
125704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                Log.v(TAG, "removeActiveSync: account=" + syncInfo.account
125804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        + " user=" + userId
12595a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams                        + " auth=" + syncInfo.authority);
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
126104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            getCurrentSyncs(userId).remove(syncInfo);
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1263360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1264918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        reportActiveChange();
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1267231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1268231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * To allow others to send active change reports, to poke clients.
1269231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1270231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public void reportActiveChange() {
1271ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
1272231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1273360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1274231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
12758ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * Note that sync has started for the given operation.
1276231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
127756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public long insertStartSyncEvent(SyncOperation op, long now) {
1278231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        long id;
1279231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
128056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (Log.isLoggable(TAG, Log.VERBOSE)) {
128156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                Log.v(TAG, "insertStartSyncEvent: " + op);
128277c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            }
128356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authority = getAuthorityLocked(op.target, "insertStartSyncEvent");
1284231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (authority == null) {
1285231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return -1;
1286231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1287231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = new SyncHistoryItem();
128856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            item.initialization = op.isInitialization();
1289231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.authorityId = authority.ident;
1290231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.historyId = mNextHistoryId++;
1291231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mNextHistoryId < 0) mNextHistoryId = 0;
1292231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.eventTime = now;
129356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            item.source = op.syncSource;
129456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            item.reason = op.reason;
129556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            item.extras = op.extras;
1296231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_START;
1297231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncHistory.add(0, item);
1298231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (mSyncHistory.size() > MAX_HISTORY) {
1299231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mSyncHistory.remove(mSyncHistory.size()-1);
1300231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1301231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            id = item.historyId;
130256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "returning historyId " + id);
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1304360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1305ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
1306231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return id;
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
130977c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana    public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
1310231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            long downstreamActivity, long upstreamActivity) {
1311231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
131256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (Log.isLoggable(TAG, Log.VERBOSE)) {
131377c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                Log.v(TAG, "stopSyncEvent: historyId=" + historyId);
131477c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            }
1315231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncHistoryItem item = null;
1316231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int i = mSyncHistory.size();
1317231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (i > 0) {
1318231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                i--;
1319231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = mSyncHistory.get(i);
1320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (item.historyId == historyId) {
1321231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                item = null;
1324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1325360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1326231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (item == null) {
1327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                Log.w(TAG, "stopSyncEvent: no history for id " + historyId);
1328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                return;
1329231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1330360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1331231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.elapsedTime = elapsedTime;
1332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.event = EVENT_STOP;
1333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.mesg = resultMessage;
1334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.downstreamActivity = downstreamActivity;
1335231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            item.upstreamActivity = upstreamActivity;
1336360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1337231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SyncStatusInfo status = getOrCreateSyncStatusLocked(item.authorityId);
1338360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1339231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.numSyncs++;
1340231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status.totalElapsedTime += elapsedTime;
1341231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            switch (item.source) {
1342231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_LOCAL:
1343231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceLocal++;
1344231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1345231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_POLL:
1346231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourcePoll++;
1347231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1348231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_USER:
1349231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceUser++;
1350231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1351231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                case SOURCE_SERVER:
1352231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.numSourceServer++;
1353231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
1354c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                case SOURCE_PERIODIC:
1355c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    status.numSourcePeriodic++;
1356c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    break;
1357231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1358360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatisticsNow = false;
136055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            int day = getCurrentDayLocked();
1361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (mDayStats[0] == null) {
1362231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
1363231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (day != mDayStats[0].day) {
1364231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                System.arraycopy(mDayStats, 0, mDayStats, 1, mDayStats.length-1);
1365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mDayStats[0] = new DayStats(day);
1366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsNow = true;
1367231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (mDayStats[0] == null) {
1368231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final DayStats ds = mDayStats[0];
1370360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final long lastSyncTime = (item.eventTime + elapsedTime);
1372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            boolean writeStatusNow = false;
1373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (MESG_SUCCESS.equals(resultMessage)) {
1374231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                // - if successful, update the successful columns
1375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastSuccessTime == 0 || status.lastFailureTime != 0) {
1376231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
1377231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1378231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessTime = lastSyncTime;
1379231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastSuccessSource = item.source;
1380231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = 0;
1381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = -1;
1382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = null;
1383231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.initialFailureTime = 0;
1384231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successCount++;
1385231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.successTime += elapsedTime;
1386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!MESG_CANCELED.equals(resultMessage)) {
1387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.lastFailureTime == 0) {
1388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    writeStatusNow = true;
1389231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1390231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureTime = lastSyncTime;
1391231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureSource = item.source;
1392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.lastFailureMesg = resultMessage;
1393231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (status.initialFailureTime == 0) {
1394231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    status.initialFailureTime = lastSyncTime;
1395231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1396231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureCount++;
1397231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ds.failureTime += elapsedTime;
1398231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1399360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1400231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatusNow) {
1401231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatusLocked();
1402231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATUS)) {
1403231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATUS),
1404231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATUS_DELAY);
1405231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1406231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (writeStatisticsNow) {
1407231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                writeStatisticsLocked();
1408231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            } else if (!hasMessages(MSG_WRITE_STATISTICS)) {
1409231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                sendMessageDelayed(obtainMessage(MSG_WRITE_STATISTICS),
1410231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        WRITE_STATISTICS_DELAY);
1411360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache            }
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1413360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1414ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1418a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams     * Return a list of the currently active syncs. Note that the returned
1419a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams     * items are the real, live active sync objects, so be careful what you do
1420a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams     * with it.
1421918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana     */
1422a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams    private List<SyncInfo> getCurrentSyncs(int userId) {
1423918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana        synchronized (mAuthorities) {
1424a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams            return getCurrentSyncsLocked(userId);
1425a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams        }
1426a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams    }
1427a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams
1428a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams    /**
1429a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams     * @return a copy of the current syncs data structure. Will not return
1430a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams     * null.
1431a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams     */
1432a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams    public List<SyncInfo> getCurrentSyncsCopy(int userId) {
1433a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams        synchronized (mAuthorities) {
1434a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams            final List<SyncInfo> syncs = getCurrentSyncsLocked(userId);
1435a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams            final List<SyncInfo> syncsCopy = new ArrayList<SyncInfo>();
1436a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams            for (SyncInfo sync : syncs) {
1437a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams                syncsCopy.add(new SyncInfo(sync));
143804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
1439a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams            return syncsCopy;
1440231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1442360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1443a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams    private List<SyncInfo> getCurrentSyncsLocked(int userId) {
1444a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams        ArrayList<SyncInfo> syncs = mCurrentSyncs.get(userId);
1445a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams        if (syncs == null) {
1446a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams            syncs = new ArrayList<SyncInfo>();
1447a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams            mCurrentSyncs.put(userId, syncs);
1448231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1449a7456e46f4cb64524386b22e2596ea93c244c16fMatthew Williams        return syncs;
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1451360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1452231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1453231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
1454231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1455231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1456231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1457231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncStatusInfo> getSyncStatus() {
1458231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1459231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
1460231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncStatusInfo> ops = new ArrayList<SyncStatusInfo>(N);
1461231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1462231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                ops.add(mSyncStatus.valueAt(i));
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1464231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ops;
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1467360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1468231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
14698ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * Return a copy of the specified target with the corresponding sync status
1470c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     */
147156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public Pair<AuthorityInfo, SyncStatusInfo> getCopyOfAuthorityWithSyncStatus(EndPoint info) {
1472c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
147356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authorityInfo = getOrCreateAuthorityLocked(info,
14748ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    -1 /* assign a new identifier if creating a new target */,
1475dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov                    true /* write to storage if this results in a change */);
1476dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov            return createCopyPairOfAuthorityWithSyncStatusLocked(authorityInfo);
1477dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov        }
1478dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov    }
1479dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov
1480dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov    /**
1481dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov     * Return a copy of all authorities with their corresponding sync status
1482dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov     */
1483dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov    public ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> getCopyOfAllAuthoritiesWithSyncStatus() {
1484dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov        synchronized (mAuthorities) {
1485dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov            ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> infos =
1486dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov                    new ArrayList<Pair<AuthorityInfo, SyncStatusInfo>>(mAuthorities.size());
1487dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov            for (int i = 0; i < mAuthorities.size(); i++) {
1488dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov                infos.add(createCopyPairOfAuthorityWithSyncStatusLocked(mAuthorities.valueAt(i)));
1489c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
1490c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return infos;
1491c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1492c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1493c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1494c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /**
14958ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * Returns the status that matches the target.
1496b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache     *
14978ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * @param info the endpoint target we are querying status info for.
14988ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * @return the SyncStatusInfo for the endpoint.
1499231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
150056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public SyncStatusInfo getStatusByAuthority(EndPoint info) {
150156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (info.target_provider && (info.account == null || info.provider == null)) {
1502d08d6686c5e16cedc23cd9bc836a28d629b8622cMatthew Williams            return null;
150356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else if (info.target_service && info.service == null) {
1504d08d6686c5e16cedc23cd9bc836a28d629b8622cMatthew Williams            return null;
1505b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache        }
1506231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1507231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
150856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            for (int i = 0; i < N; i++) {
1509360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                SyncStatusInfo cur = mSyncStatus.valueAt(i);
1510231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
151156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (ainfo != null
15128ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        && ainfo.target.matchesSpec(info)) {
1513b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache                  return cur;
1514231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1515231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1516b752098e8d12d6e7925d97458078dbb896ca8a05Costin Manolache            return null;
1517231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1519360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
152056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /** Return true if the pending status is true of any matching authorities. */
152156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public boolean isSyncPending(EndPoint info) {
1522231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1523231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
152456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            for (int i = 0; i < N; i++) {
1525360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                SyncStatusInfo cur = mSyncStatus.valueAt(i);
1526231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                AuthorityInfo ainfo = mAuthorities.get(cur.authorityId);
1527231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ainfo == null) {
1528231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    continue;
1529231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
15308ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                if (!ainfo.target.matchesSpec(info)) {
153104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    continue;
153204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                }
153356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (cur.pending) {
1534231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    return true;
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1537231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return false;
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1542231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current sync status for all authorities.  Note
1543231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1544231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1545231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1546231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public ArrayList<SyncHistoryItem> getSyncHistory() {
1547231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1548231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncHistory.size();
1549231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            ArrayList<SyncHistoryItem> items = new ArrayList<SyncHistoryItem>(N);
1550231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
1551231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                items.add(mSyncHistory.get(i));
1552231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1553231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return items;
1554231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1555231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1556360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1557231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1558231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Return an array of the current per-day statistics.  Note
1559231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * that the objects inside the array are the real, live status objects,
1560231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * so be careful what you do with them.
1561231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1562231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public DayStats[] getDayStatistics() {
1563231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        synchronized (mAuthorities) {
1564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            DayStats[] ds = new DayStats[mDayStats.length];
1565231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            System.arraycopy(mDayStats, 0, ds, 0, ds.length);
1566231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return ds;
1567231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1568231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1569360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1570dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov    private Pair<AuthorityInfo, SyncStatusInfo> createCopyPairOfAuthorityWithSyncStatusLocked(
1571dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov            AuthorityInfo authorityInfo) {
1572dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov        SyncStatusInfo syncStatusInfo = getOrCreateSyncStatusLocked(authorityInfo.ident);
1573dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov        return Pair.create(new AuthorityInfo(authorityInfo), new SyncStatusInfo(syncStatusInfo));
1574dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov    }
1575dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov
157655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private int getCurrentDayLocked() {
1577231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        mCal.setTimeInMillis(System.currentTimeMillis());
1578231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
1579231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (mYear != mCal.get(Calendar.YEAR)) {
1580231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYear = mCal.get(Calendar.YEAR);
1581231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.clear();
1582231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mCal.set(Calendar.YEAR, mYear);
1583231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mYearInDays = (int)(mCal.getTimeInMillis()/86400000);
1584231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1585231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return dayOfYear + mYearInDays;
1586231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1587360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1588231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
15898ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * Retrieve a target's full info, returning null if one does not exist.
1590360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache     *
15918ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * @param info info of the target to look up.
1592231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * @param tag If non-null, this will be used in a log message if the
15938ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * requested target does not exist.
1594231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
159556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    private AuthorityInfo getAuthorityLocked(EndPoint info, String tag) {
159656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (info.target_service) {
159756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            SparseArray<AuthorityInfo> aInfo = mServices.get(info.service);
159856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authority = null;
159956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (aInfo != null) {
160056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                authority = aInfo.get(info.userId);
160156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
160256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (authority == null) {
160356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (tag != null) {
160456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
16058ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        Log.v(TAG, tag + " No authority info found for " + info.service + " for"
16068ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                + " user " + info.userId);
160756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    }
1608b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                }
160956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                return null;
1610231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
161156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return authority;
161256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else if (info.target_provider){
161356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AccountAndUser au = new AccountAndUser(info.account, info.userId);
161456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AccountInfo accountInfo = mAccounts.get(au);
161556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (accountInfo == null) {
161656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (tag != null) {
161756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
161856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        Log.v(TAG, tag + ": unknown account " + au);
161956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    }
1620b763ab265130b5aa59e4de561ba3836ac294fe62Fred Quintana                }
162156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                return null;
1622231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
162356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo authority = accountInfo.authorities.get(info.provider);
162456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (authority == null) {
162556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (tag != null) {
162656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
162756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        Log.v(TAG, tag + ": unknown provider " + info.provider);
162856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    }
1629fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                }
163056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                return null;
1631fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            }
163256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            return authority;
163356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else {
163456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            Log.e(TAG, tag + " Authority : " + info + ", invalid target");
1635fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            return null;
1636fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        }
1637fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    }
1638fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
1639fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
16408ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * @param info info identifying target.
16418ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * @param ident unique identifier for target. -1 for none.
1642fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * @param doWrite if true, update the accounts.xml file on the disk.
16438ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * @return the authority that corresponds to the provided sync target, creating it if none
1644fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * exists.
1645fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
164656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    private AuthorityInfo getOrCreateAuthorityLocked(EndPoint info, int ident, boolean doWrite) {
164756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        AuthorityInfo authority = null;
164856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (info.target_service) {
164956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            SparseArray<AuthorityInfo> aInfo = mServices.get(info.service);
165056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (aInfo == null) {
165156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                aInfo = new SparseArray<AuthorityInfo>();
165256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                mServices.put(info.service, aInfo);
165356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
165456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            authority = aInfo.get(info.userId);
165556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (authority == null) {
165656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                authority = createAuthorityLocked(info, ident, doWrite);
165756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                aInfo.put(info.userId, authority);
165856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
165956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else if (info.target_provider) {
166056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AccountAndUser au = new AccountAndUser(info.account, info.userId);
166156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AccountInfo account = mAccounts.get(au);
166256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (account == null) {
166356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                account = new AccountInfo(au);
166456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                mAccounts.put(au, account);
166556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
166656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            authority = account.authorities.get(info.provider);
166756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (authority == null) {
166856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                authority = createAuthorityLocked(info, ident, doWrite);
166956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                account.authorities.put(info.provider, authority);
1670fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            }
1671fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        }
1672fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        return authority;
1673fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    }
1674fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
167556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    private AuthorityInfo createAuthorityLocked(EndPoint info, int ident, boolean doWrite) {
167656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        AuthorityInfo authority;
167756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (ident < 0) {
167856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            ident = mNextAuthorityId;
167956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            mNextAuthorityId++;
168056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            doWrite = true;
168156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
168256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (Log.isLoggable(TAG, Log.VERBOSE)) {
168356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            Log.v(TAG, "created a new AuthorityInfo for " + info);
168456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
168556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        authority = new AuthorityInfo(info, ident);
168656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        mAuthorities.put(ident, authority);
168756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (doWrite) {
168856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            writeAccountInfoLocked();
1689231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1690231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return authority;
1691231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1692360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
169356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public void removeAuthority(EndPoint info) {
169456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        synchronized (mAuthorities) {
169556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (info.target_provider) {
169656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                removeAuthorityLocked(info.account, info.userId, info.provider, true /* doWrite */);
169756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            } else {
169856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                SparseArray<AuthorityInfo> aInfos = mServices.get(info.service);
169956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (aInfos != null) {
170056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    AuthorityInfo authorityInfo = aInfos.get(info.userId);
170156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    if (authorityInfo != null) {
170256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        mAuthorities.remove(authorityInfo.ident);
170356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        aInfos.delete(info.userId);
170456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        writeAccountInfoLocked();
170556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    }
170656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                }
170756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
170856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
170956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
171056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
171156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
171256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    /**
171356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * Remove an authority associated with a provider. Needs to be a standalone function for
171456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     * backward compatibility.
171556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams     */
171604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void removeAuthorityLocked(Account account, int userId, String authorityName,
171704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            boolean doWrite) {
171804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        AccountInfo accountInfo = mAccounts.get(new AccountAndUser(account, userId));
17197620f1ae498e01bf2df58eaa1b9b20ef1eb47fa1Fred Quintana        if (accountInfo != null) {
1720fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            final AuthorityInfo authorityInfo = accountInfo.authorities.remove(authorityName);
1721fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            if (authorityInfo != null) {
1722fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana                mAuthorities.remove(authorityInfo.ident);
172377c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                if (doWrite) {
172477c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                    writeAccountInfoLocked();
172577c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                }
17267620f1ae498e01bf2df58eaa1b9b20ef1eb47fa1Fred Quintana            }
17277620f1ae498e01bf2df58eaa1b9b20ef1eb47fa1Fred Quintana        }
17287620f1ae498e01bf2df58eaa1b9b20ef1eb47fa1Fred Quintana    }
17297620f1ae498e01bf2df58eaa1b9b20ef1eb47fa1Fred Quintana
1730dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov    /**
1731dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov     * Updates (in a synchronized way) the periodic sync time of the specified
17328ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * target id and target periodic sync
1733dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov     */
173456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    public void setPeriodicSyncTime(int authorityId, PeriodicSync targetPeriodicSync, long when) {
173544c4ddfd47f08f542745a512fbdcd0b551d88b2eGeorgi Nikolov        boolean found = false;
173644c4ddfd47f08f542745a512fbdcd0b551d88b2eGeorgi Nikolov        final AuthorityInfo authorityInfo;
1737c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
173844c4ddfd47f08f542745a512fbdcd0b551d88b2eGeorgi Nikolov            authorityInfo = mAuthorities.get(authorityId);
173944c4ddfd47f08f542745a512fbdcd0b551d88b2eGeorgi Nikolov            for (int i = 0; i < authorityInfo.periodicSyncs.size(); i++) {
1740fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                PeriodicSync periodicSync = authorityInfo.periodicSyncs.get(i);
1741fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                if (targetPeriodicSync.equals(periodicSync)) {
1742dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov                    mSyncStatus.get(authorityId).setPeriodicSyncTime(i, when);
174344c4ddfd47f08f542745a512fbdcd0b551d88b2eGeorgi Nikolov                    found = true;
1744dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov                    break;
1745dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov                }
1746dbe846b02e6f6f715787cf8621587f7bc25deaacGeorgi Nikolov            }
1747c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
174844c4ddfd47f08f542745a512fbdcd0b551d88b2eGeorgi Nikolov        if (!found) {
174944c4ddfd47f08f542745a512fbdcd0b551d88b2eGeorgi Nikolov            Log.w(TAG, "Ignoring setPeriodicSyncTime request for a sync that does not exist. " +
17508ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    "Authority: " + authorityInfo.target);
175144c4ddfd47f08f542745a512fbdcd0b551d88b2eGeorgi Nikolov        }
1752c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1753c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1754231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private SyncStatusInfo getOrCreateSyncStatusLocked(int authorityId) {
1755231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SyncStatusInfo status = mSyncStatus.get(authorityId);
1756231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (status == null) {
1757231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            status = new SyncStatusInfo(authorityId);
1758231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mSyncStatus.put(authorityId, status);
1759231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1760231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return status;
1761231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1762360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
176355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    public void writeAllState() {
176455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        synchronized (mAuthorities) {
176555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Account info is always written so no need to do it here.
1766360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
176755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            if (mNumPendingFinished > 0) {
176855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                // Only write these if they are out of date.
176955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                writePendingOperationsLocked();
177055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
1771360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
177255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            // Just always write these...  they are likely out of date.
177355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatusLocked();
177455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            writeStatisticsLocked();
177555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
177655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
1777360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1778231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
1779c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     * public for testing
1780c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana     */
1781c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    public void clearAndReadState() {
1782c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        synchronized (mAuthorities) {
1783c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mAuthorities.clear();
1784c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mAccounts.clear();
1785fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            mServices.clear();
1786c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mPendingOperations.clear();
1787c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mSyncStatus.clear();
1788c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            mSyncHistory.clear();
1789c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1790c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readAccountInfoLocked();
1791c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readStatusLocked();
1792c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readPendingOperationsLocked();
1793c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            readStatisticsLocked();
179477c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            readAndDeleteLegacyAccountInfoLocked();
179577c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            writeAccountInfoLocked();
179677c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            writeStatusLocked();
179777c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            writePendingOperationsLocked();
179877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            writeStatisticsLocked();
1799c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1800c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
1801c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
1802c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    /**
1803231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all account information back in to the initial engine state.
1804231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
1805231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readAccountInfoLocked() {
180677c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        int highestAuthorityId = -1;
1807231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileInputStream fis = null;
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1809231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fis = mAccountInfoFile.openRead();
1810ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
18118ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                Log.v(TAG_FILE, "Reading " + mAccountInfoFile.getBaseFile());
1812ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            }
1813231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlPullParser parser = Xml.newPullParser();
1814231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            parser.setInput(fis, null);
1815231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int eventType = parser.getEventType();
18162ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath            while (eventType != XmlPullParser.START_TAG &&
18172ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath                    eventType != XmlPullParser.END_DOCUMENT) {
1818231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1819231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
18202ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath            if (eventType == XmlPullParser.END_DOCUMENT) {
18212ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath                Log.i(TAG, "No initial accounts");
18222ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath                return;
18232ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath            }
18242ac3cb7aef7c8a51cbeb6d34b648dedcb4363994Narayan Kamath
1825231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            String tagName = parser.getName();
1826231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if ("accounts".equals(tagName)) {
182704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                String listen = parser.getAttributeValue(null, XML_ATTR_LISTEN_FOR_TICKLES);
1828c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                String versionString = parser.getAttributeValue(null, "version");
1829c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                int version;
1830c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                try {
1831c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                    version = (versionString == null) ? 0 : Integer.parseInt(versionString);
1832c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                } catch (NumberFormatException e) {
1833c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                    version = 0;
1834c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                }
183504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                String nextIdString = parser.getAttributeValue(null, XML_ATTR_NEXT_AUTHORITY_ID);
183677c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                try {
183777c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                    int id = (nextIdString == null) ? 0 : Integer.parseInt(nextIdString);
183877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                    mNextAuthorityId = Math.max(mNextAuthorityId, id);
183977c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                } catch (NumberFormatException e) {
184077c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                    // don't care
1841c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                }
184269d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                String offsetString = parser.getAttributeValue(null, XML_ATTR_SYNC_RANDOM_OFFSET);
184369d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                try {
184469d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                    mSyncRandomOffset = (offsetString == null) ? 0 : Integer.parseInt(offsetString);
184569d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                } catch (NumberFormatException e) {
184669d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                    mSyncRandomOffset = 0;
184769d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                }
184869d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                if (mSyncRandomOffset == 0) {
184969d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                    Random random = new Random(System.currentTimeMillis());
185069d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                    mSyncRandomOffset = random.nextInt(86400);
185169d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma                }
185204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                mMasterSyncAutomatically.put(0, listen == null || Boolean.parseBoolean(listen));
1853231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                eventType = parser.next();
1854c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                AuthorityInfo authority = null;
1855fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                PeriodicSync periodicSync = null;
1856231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                do {
1857c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    if (eventType == XmlPullParser.START_TAG) {
1858231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        tagName = parser.getName();
1859c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        if (parser.getDepth() == 2) {
1860c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            if ("authority".equals(tagName)) {
1861c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                                authority = parseAuthority(parser, version);
1862c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                periodicSync = null;
186377c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                                if (authority.ident > highestAuthorityId) {
186477c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                                    highestAuthorityId = authority.ident;
186577c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana                                }
186604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                            } else if (XML_TAG_LISTEN_FOR_TICKLES.equals(tagName)) {
186704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                                parseListenForTickles(parser);
1868231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1869c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (parser.getDepth() == 3) {
1870c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            if ("periodicSync".equals(tagName) && authority != null) {
1871c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                                periodicSync = parsePeriodicSync(parser, authority);
1872c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            }
1873c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        } else if (parser.getDepth() == 4 && periodicSync != null) {
1874c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                            if ("extra".equals(tagName)) {
1875fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                                parseExtra(parser, periodicSync.extras);
1876231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            }
1877231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
1878231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
1879231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    eventType = parser.next();
1880231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } while (eventType != XmlPullParser.END_DOCUMENT);
1881231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1882231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (XmlPullParserException e) {
1883231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error reading accounts", e);
1884c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana            return;
1885231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
1886231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis == null) Log.i(TAG, "No initial accounts");
1887231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            else Log.w(TAG, "Error reading accounts", e);
1888c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana            return;
1889231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } finally {
189077c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana            mNextAuthorityId = Math.max(highestAuthorityId + 1, mNextAuthorityId);
1891231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fis != null) {
1892231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                try {
1893231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    fis.close();
1894231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } catch (java.io.IOException e1) {
1895231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
1896231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
1897231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
1898c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana
189977c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana        maybeMigrateSettingsForRenamedAuthorities();
1900231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
1901360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
1902fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana    /**
1903ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams     * Ensure the old pending.bin is deleted, as it has been changed to pending.xml.
1904ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams     * pending.xml was used starting in KLP.
1905ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams     * @param syncDir directory where the sync files are located.
1906ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams     */
1907ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    private void maybeDeleteLegacyPendingInfoLocked(File syncDir) {
1908ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        File file = new File(syncDir, "pending.bin");
1909ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        if (!file.exists()) {
1910ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            return;
1911ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        } else {
1912ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            file.delete();
1913ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        }
1914ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    }
1915ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams
1916ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    /**
1917fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana     * some authority names have changed. copy over their settings and delete the old ones
1918fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana     * @return true if a change was made
1919fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana     */
1920fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana    private boolean maybeMigrateSettingsForRenamedAuthorities() {
1921fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        boolean writeNeeded = false;
1922fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
1923fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        ArrayList<AuthorityInfo> authoritiesToRemove = new ArrayList<AuthorityInfo>();
1924fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        final int N = mAuthorities.size();
192556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        for (int i = 0; i < N; i++) {
1926fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            AuthorityInfo authority = mAuthorities.valueAt(i);
19278ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            // skip this authority if it doesn't target a provider
19288ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            if (authority.target.target_service) {
19298ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                continue;
19308ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            }
1931fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            // skip this authority if it isn't one of the renamed ones
19328ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            final String newAuthorityName = sAuthorityRenames.get(authority.target.provider);
1933fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            if (newAuthorityName == null) {
1934fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana                continue;
1935fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            }
1936fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
1937fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            // remember this authority so we can remove it later. we can't remove it
1938fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            // now without messing up this loop iteration
1939fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            authoritiesToRemove.add(authority);
1940fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
1941fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            // this authority isn't enabled, no need to copy it to the new authority name since
1942fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            // the default is "disabled"
1943fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            if (!authority.enabled) {
1944fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana                continue;
1945fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            }
1946fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
1947fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            // if we already have a record of this new authority then don't copy over the settings
194856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            EndPoint newInfo =
19498ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    new EndPoint(authority.target.account,
195056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                            newAuthorityName,
19518ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            authority.target.userId);
195256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            if (getAuthorityLocked(newInfo, "cleanup") != null) {
1953fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana                continue;
1954fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            }
1955fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
195656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            AuthorityInfo newAuthority =
195756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    getOrCreateAuthorityLocked(newInfo, -1 /* ident */, false /* doWrite */);
1958fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            newAuthority.enabled = true;
1959fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            writeNeeded = true;
1960fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        }
1961fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
1962fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        for (AuthorityInfo authorityInfo : authoritiesToRemove) {
196356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            removeAuthorityLocked(
19648ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    authorityInfo.target.account,
19658ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    authorityInfo.target.userId,
19668ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    authorityInfo.target.provider,
196756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    false /* doWrite */);
1968fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            writeNeeded = true;
1969fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        }
1970fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
1971fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana        return writeNeeded;
1972fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana    }
1973fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana
197404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void parseListenForTickles(XmlPullParser parser) {
197504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        String user = parser.getAttributeValue(null, XML_ATTR_USER);
197604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        int userId = 0;
197704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        try {
197804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            userId = Integer.parseInt(user);
197904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        } catch (NumberFormatException e) {
198004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Log.e(TAG, "error parsing the user for listen-for-tickles", e);
198104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        } catch (NullPointerException e) {
198204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Log.e(TAG, "the user in listen-for-tickles is null", e);
198304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
198404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        String enabled = parser.getAttributeValue(null, XML_ATTR_ENABLED);
198504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        boolean listen = enabled == null || Boolean.parseBoolean(enabled);
198604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        mMasterSyncAutomatically.put(userId, listen);
198704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
198804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
1989c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana    private AuthorityInfo parseAuthority(XmlPullParser parser, int version) {
1990c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        AuthorityInfo authority = null;
1991c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        int id = -1;
1992c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
1993fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            id = Integer.parseInt(parser.getAttributeValue(null, "id"));
1994c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NumberFormatException e) {
1995c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing the id of the authority", e);
1996c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NullPointerException e) {
1997c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "the id of the authority is null", e);
1998c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
1999c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        if (id >= 0) {
2000fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            String authorityName = parser.getAttributeValue(null, "authority");
200104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String enabled = parser.getAttributeValue(null, XML_ATTR_ENABLED);
2002fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana            String syncable = parser.getAttributeValue(null, "syncable");
2003c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String accountName = parser.getAttributeValue(null, "account");
2004c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            String accountType = parser.getAttributeValue(null, "type");
200504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String user = parser.getAttributeValue(null, XML_ATTR_USER);
2006fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            String packageName = parser.getAttributeValue(null, "package");
2007fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            String className = parser.getAttributeValue(null, "class");
200804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            int userId = user == null ? 0 : Integer.parseInt(user);
20098ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            if (accountType == null && packageName == null) {
2010c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                accountType = "com.google";
2011fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana                syncable = "unknown";
2012c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
2013c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            authority = mAuthorities.get(id);
2014ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
20158ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                Log.v(TAG_FILE, "Adding authority:"
20168ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        + " account=" + accountName
20178ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        + " accountType=" + accountType
20188ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        + " auth=" + authorityName
20198ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        + " package=" + packageName
20208ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        + " class=" + className
2021ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                        + " user=" + userId
2022ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                        + " enabled=" + enabled
2023ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                        + " syncable=" + syncable);
2024ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            }
2025c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (authority == null) {
2026ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
202756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    Log.v(TAG_FILE, "Creating authority entry");
2028fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                }
20298ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                EndPoint info;
20308ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                if (accountName != null && authorityName != null) {
20318ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    info = new EndPoint(
20328ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            new Account(accountName, accountType),
20338ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            authorityName, userId);
2034fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                } else {
20358ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    info = new EndPoint(
20368ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            new ComponentName(packageName, className),
20378ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            userId);
2038fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                }
20398ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                authority = getOrCreateAuthorityLocked(info, id, false);
2040c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                // If the version is 0 then we are upgrading from a file format that did not
2041c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                // know about periodic syncs. In that case don't clear the list since we
2042fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                // want the default, which is a daily periodic sync.
2043c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                // Otherwise clear out this default list since we will populate it later with
2044c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                // the periodic sync descriptions that are read from the configuration file.
2045c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                if (version > 0) {
2046c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                    authority.periodicSyncs.clear();
2047c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana                }
2048c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
2049c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if (authority != null) {
2050c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                authority.enabled = enabled == null || Boolean.parseBoolean(enabled);
2051c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                if ("unknown".equals(syncable)) {
2052c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    authority.syncable = -1;
2053c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                } else {
2054c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    authority.syncable =
2055fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana                            (syncable == null || Boolean.parseBoolean(syncable)) ? 1 : 0;
2056c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
2057c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else {
2058c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                Log.w(TAG, "Failure adding authority: account="
2059c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        + accountName + " auth=" + authorityName
2060c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        + " enabled=" + enabled
2061c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                        + " syncable=" + syncable);
2062c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
2063c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
2064c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return authority;
2065c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
2066c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
2067fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
2068fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * Parse a periodic sync from accounts.xml. Sets the bundle to be empty.
2069fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
207056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    private PeriodicSync parsePeriodicSync(XmlPullParser parser, AuthorityInfo authorityInfo) {
2071fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        Bundle extras = new Bundle(); // Gets filled in later.
2072c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String periodValue = parser.getAttributeValue(null, "period");
2073fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        String flexValue = parser.getAttributeValue(null, "flex");
2074c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        final long period;
2075fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        long flextime;
2076c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
2077c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            period = Long.parseLong(periodValue);
2078c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NumberFormatException e) {
2079c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing the period of a periodic sync", e);
2080c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return null;
2081c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NullPointerException e) {
2082c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "the period of a periodic sync is null", e);
2083c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            return null;
2084c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
2085fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        try {
2086fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            flextime = Long.parseLong(flexValue);
2087fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        } catch (NumberFormatException e) {
2088fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            flextime = calculateDefaultFlexTime(period);
20898ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            Log.e(TAG, "Error formatting value parsed for periodic sync flex: " + flexValue
20908ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    + ", using default: "
20918ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    + flextime);
2092fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        } catch (NullPointerException expected) {
2093fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            flextime = calculateDefaultFlexTime(period);
2094fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            Log.d(TAG, "No flex time specified for this sync, using a default. period: "
2095fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            + period + " flex: " + flextime);
2096fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        }
209756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        PeriodicSync periodicSync;
20988ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        if (authorityInfo.target.target_provider) {
209956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            periodicSync =
21008ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                new PeriodicSync(authorityInfo.target.account,
21018ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        authorityInfo.target.provider,
210256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        extras,
2103fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                        period, flextime);
210456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else {
21055a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams            Log.e(TAG, "Unknown target.");
21065a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams            return null;
210756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
210856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        authorityInfo.periodicSyncs.add(periodicSync);
2109c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        return periodicSync;
2110c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
2111c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
2112fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    private void parseExtra(XmlPullParser parser, Bundle extras) {
2113c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String name = parser.getAttributeValue(null, "name");
2114c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String type = parser.getAttributeValue(null, "type");
2115c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String value1 = parser.getAttributeValue(null, "value1");
2116c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        String value2 = parser.getAttributeValue(null, "value2");
2117c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
2118c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        try {
2119c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            if ("long".equals(type)) {
2120c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putLong(name, Long.parseLong(value1));
2121c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("integer".equals(type)) {
2122c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putInt(name, Integer.parseInt(value1));
2123c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("double".equals(type)) {
2124c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putDouble(name, Double.parseDouble(value1));
2125c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("float".equals(type)) {
2126c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putFloat(name, Float.parseFloat(value1));
2127c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("boolean".equals(type)) {
2128c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putBoolean(name, Boolean.parseBoolean(value1));
2129c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("string".equals(type)) {
2130c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putString(name, value1);
2131c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            } else if ("account".equals(type)) {
2132c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                extras.putParcelable(name, new Account(value1, value2));
2133c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            }
2134c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NumberFormatException e) {
2135c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing bundle value", e);
2136c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        } catch (NullPointerException e) {
2137c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana            Log.e(TAG, "error parsing bundle value", e);
2138c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana        }
2139c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana    }
2140c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana
2141231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
2142231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all account information to the account file.
2143231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
2144231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeAccountInfoLocked() {
2145ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
21468ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            Log.v(TAG_FILE, "Writing new " + mAccountInfoFile.getBaseFile());
2147ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        }
2148231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
2149360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2150231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
2151231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mAccountInfoFile.startWrite();
2152231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            XmlSerializer out = new FastXmlSerializer();
2153231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setOutput(fos, "utf-8");
2154231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startDocument(null, true);
2155231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
2156360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2157231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.startTag(null, "accounts");
2158c2e4691d788088b22eadc9b2d35e9bdf0b6a0ffcFred Quintana            out.attribute(null, "version", Integer.toString(ACCOUNTS_VERSION));
215904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            out.attribute(null, XML_ATTR_NEXT_AUTHORITY_ID, Integer.toString(mNextAuthorityId));
216069d95de53bc82e6c23c64ad566e428fbefae0543Ashish Sharma            out.attribute(null, XML_ATTR_SYNC_RANDOM_OFFSET, Integer.toString(mSyncRandomOffset));
216104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
216204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            // Write the Sync Automatically flags for each user
216304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final int M = mMasterSyncAutomatically.size();
216404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (int m = 0; m < M; m++) {
216504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                int userId = mMasterSyncAutomatically.keyAt(m);
216604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                Boolean listen = mMasterSyncAutomatically.valueAt(m);
216704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                out.startTag(null, XML_TAG_LISTEN_FOR_TICKLES);
216804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                out.attribute(null, XML_ATTR_USER, Integer.toString(userId));
216904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                out.attribute(null, XML_ATTR_ENABLED, Boolean.toString(listen));
217004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                out.endTag(null, XML_TAG_LISTEN_FOR_TICKLES);
2171231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2172360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2173231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mAuthorities.size();
2174fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            for (int i = 0; i < N; i++) {
2175360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                AuthorityInfo authority = mAuthorities.valueAt(i);
21768ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                EndPoint info = authority.target;
2177231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.startTag(null, "authority");
2178231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.attribute(null, "id", Integer.toString(authority.ident));
217956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                out.attribute(null, XML_ATTR_USER, Integer.toString(info.userId));
218004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                out.attribute(null, XML_ATTR_ENABLED, Boolean.toString(authority.enabled));
218156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (info.service == null) {
218256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    out.attribute(null, "account", info.account.name);
218356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    out.attribute(null, "type", info.account.type);
218456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    out.attribute(null, "authority", info.provider);
2185fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                } else {
218656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    out.attribute(null, "package", info.service.getPackageName());
218756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    out.attribute(null, "class", info.service.getClassName());
2188fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                }
21895e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                if (authority.syncable < 0) {
21905e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                    out.attribute(null, "syncable", "unknown");
2191fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana                } else {
2192fb084400d6afa6443a421117fbcaee0265d38fb6Fred Quintana                    out.attribute(null, "syncable", Boolean.toString(authority.syncable != 0));
21935e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                }
2194fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                for (PeriodicSync periodicSync : authority.periodicSyncs) {
2195c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    out.startTag(null, "periodicSync");
2196fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    out.attribute(null, "period", Long.toString(periodicSync.period));
2197fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    out.attribute(null, "flex", Long.toString(periodicSync.flexTime));
2198fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    final Bundle extras = periodicSync.extras;
2199fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    extrasToXml(out, extras);
2200c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    out.endTag(null, "periodicSync");
2201c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                }
2202231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.endTag(null, "authority");
2203231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2204231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endTag(null, "accounts");
2205231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.endDocument();
2206231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mAccountInfoFile.finishWrite(fos);
2207231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
2208231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing accounts", e1);
2209231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
2210231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mAccountInfoFile.failWrite(fos);
2211231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2212231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
2213231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
2214360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2215231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static int getIntColumn(Cursor c, String name) {
2216231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getInt(c.getColumnIndex(name));
2217231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
2218360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2219231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    static long getLongColumn(Cursor c, String name) {
2220231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        return c.getLong(c.getColumnIndex(name));
2221231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
2222360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2223231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
2224231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Load sync engine state from the old syncmanager database, and then
2225231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * erase it.  Note that we don't deal with pending operations, active
2226231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * sync, or history.
2227231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
222877c560f3d7891d9ae1ad714b5f65a22ff4f4c06bFred Quintana    private void readAndDeleteLegacyAccountInfoLocked() {
2229231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // Look for old database to initialize from.
2230231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        File file = mContext.getDatabasePath("syncmanager.db");
2231231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (!file.exists()) {
2232231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            return;
2233231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
2234231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        String path = file.getPath();
2235231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        SQLiteDatabase db = null;
2236231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
2237231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db = SQLiteDatabase.openDatabase(path, null,
2238231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SQLiteDatabase.OPEN_READONLY);
2239231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (SQLiteException e) {
2240231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
2241360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2242231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        if (db != null) {
22432d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            final boolean hasType = db.getVersion() >= 11;
2244360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2245231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Copy in all of the status information, as well as accounts.
2246ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
22478ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                Log.v(TAG_FILE, "Reading legacy sync accounts db");
2248ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            }
2249231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
2250231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("stats, status");
2251231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            HashMap<String,String> map = new HashMap<String,String>();
2252231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("_id", "status._id as _id");
2253231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("account", "stats.account as account");
22542d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            if (hasType) {
22552d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                map.put("account_type", "stats.account_type as account_type");
22562d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn            }
2257231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("authority", "stats.authority as authority");
2258231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("totalElapsedTime", "totalElapsedTime");
2259231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSyncs", "numSyncs");
2260231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceLocal", "numSourceLocal");
2261231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourcePoll", "numSourcePoll");
2262231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceServer", "numSourceServer");
2263231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("numSourceUser", "numSourceUser");
2264231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessSource", "lastSuccessSource");
2265231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastSuccessTime", "lastSuccessTime");
2266231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureSource", "lastFailureSource");
2267231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureTime", "lastFailureTime");
2268231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("lastFailureMesg", "lastFailureMesg");
2269231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            map.put("pending", "pending");
2270231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setProjectionMap(map);
2271231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.appendWhere("stats._id = status.stats_id");
2272231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Cursor c = qb.query(db, null, null, null, null, null, null);
22739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            while (c.moveToNext()) {
2274231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String accountName = c.getString(c.getColumnIndex("account"));
22752d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                String accountType = hasType
22762d5ed1fa3d29cdf1afb3bdfc3fc6a061f9f3feb3Dianne Hackborn                        ? c.getString(c.getColumnIndex("account_type")) : null;
22777a1355950172b7a549820e9a2cd4a9b2099ec32fDianne Hackborn                if (accountType == null) {
22783348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                    accountType = "com.google";
22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2280231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String authorityName = c.getString(c.getColumnIndex("authority"));
228156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                AuthorityInfo authority =
228256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                        this.getOrCreateAuthorityLocked(
228356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                new EndPoint(new Account(accountName, accountType),
228456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                        authorityName,
228556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                        0 /* legacy is single-user */)
228656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                , -1,
228756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                false);
2288231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (authority != null) {
2289231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int i = mSyncStatus.size();
2290231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    boolean found = false;
2291231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo st = null;
2292231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    while (i > 0) {
2293231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        i--;
2294360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                        st = mSyncStatus.valueAt(i);
2295231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        if (st.authorityId == authority.ident) {
2296231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            found = true;
2297231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            break;
2298231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        }
2299231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
2300231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (!found) {
2301231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        st = new SyncStatusInfo(authority.ident);
2302231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(authority.ident, st);
2303231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
2304231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.totalElapsedTime = getLongColumn(c, "totalElapsedTime");
2305231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSyncs = getIntColumn(c, "numSyncs");
2306231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceLocal = getIntColumn(c, "numSourceLocal");
2307231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourcePoll = getIntColumn(c, "numSourcePoll");
2308231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceServer = getIntColumn(c, "numSourceServer");
2309231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.numSourceUser = getIntColumn(c, "numSourceUser");
2310c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana                    st.numSourcePeriodic = 0;
2311231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessSource = getIntColumn(c, "lastSuccessSource");
2312231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastSuccessTime = getLongColumn(c, "lastSuccessTime");
2313231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureSource = getIntColumn(c, "lastFailureSource");
2314231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureTime = getLongColumn(c, "lastFailureTime");
2315231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.lastFailureMesg = c.getString(c.getColumnIndex("lastFailureMesg"));
2316231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    st.pending = getIntColumn(c, "pending") != 0;
23179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2319360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2320231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c.close();
2321360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2322231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            // Retrieve the settings.
2323231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb = new SQLiteQueryBuilder();
2324231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            qb.setTables("settings");
2325231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            c = qb.query(db, null, null, null, null, null, null);
2326231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while (c.moveToNext()) {
2327231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String name = c.getString(c.getColumnIndex("name"));
2328231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                String value = c.getString(c.getColumnIndex("value"));
2329231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name == null) continue;
2330231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (name.equals("listen_for_tickles")) {
233104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    setMasterSyncAutomatically(value == null || Boolean.parseBoolean(value), 0);
2332231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else if (name.startsWith("sync_provider_")) {
2333231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    String provider = name.substring("sync_provider_".length(),
2334231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                            name.length());
2335ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    int i = mAuthorities.size();
2336ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    while (i > 0) {
2337ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        i--;
2338360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache                        AuthorityInfo authority = mAuthorities.valueAt(i);
23398ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        if (authority.target.provider.equals(provider)) {
2340ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                            authority.enabled = value == null || Boolean.parseBoolean(value);
23415e787c42f2a6b3afc8ec8320a08d51b2d44b8614Fred Quintana                            authority.syncable = 1;
2342ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                        }
2343ac9385ef3105fb7464e1f46049c62755a8b7f0e9Fred Quintana                    }
23449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2346360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
23479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.close();
2348360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2349231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            db.close();
2350360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2351231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            (new File(path)).delete();
23529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2354360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2355231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_END = 0;
2356231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATUS_FILE_ITEM = 100;
2357360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2358231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
2359231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync status back in to the initial engine state.
2360231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
2361231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatusLocked() {
2362ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
23638ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            Log.v(TAG_FILE, "Reading " + mStatusFile.getBaseFile());
2364ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        }
2365231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
2366231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatusFile.readFully();
2367231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
2368231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
2369231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
2370231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
2371231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATUS_FILE_END) {
2372231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATUS_FILE_ITEM) {
2373231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    SyncStatusInfo status = new SyncStatusInfo(in);
2374231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (mAuthorities.indexOfKey(status.authorityId) >= 0) {
2375231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        status.pending = false;
2376ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
23778ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            Log.v(TAG_FILE, "Adding status for id " + status.authorityId);
2378ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                        }
2379231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mSyncStatus.put(status.authorityId, status);
2380231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
2381231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
2382231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
2383231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown status token: " + token);
2384231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
2385231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
2386231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2387231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
2388231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial status");
23899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2391360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2392231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
2393231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync status to the sync status file.
2394231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
2395231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatusLocked() {
2396ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
23978ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            Log.v(TAG_FILE, "Writing new " + mStatusFile.getBaseFile());
2398ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        }
2399360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2400231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
2401231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
2402231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATUS);
2403360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2404231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
24059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2406231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatusFile.startWrite();
2407231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
2408231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mSyncStatus.size();
2409231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
2410231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                SyncStatusInfo status = mSyncStatus.valueAt(i);
2411231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATUS_FILE_ITEM);
2412231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                status.writeToParcel(out, 0);
24139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2414231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATUS_FILE_END);
2415231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
2416231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
2417360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2418231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatusFile.finishWrite(fos);
2419231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
2420231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing status", e1);
2421231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
2422231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatusFile.failWrite(fos);
2423231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2424231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
2425231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
2426360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2427ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    public static final int PENDING_OPERATION_VERSION = 3;
2428360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2429ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    /** Read all pending operations back in to the initial engine state. */
2430231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readPendingOperationsLocked() {
2431ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        FileInputStream fis = null;
2432ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        if (!mPendingFile.getBaseFile().exists()) {
2433ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
2434ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                Log.v(TAG_FILE, "No pending operation file.");
2435231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2436886113dfca52d5ee92376fc50eaaee9d0bab3b09Ji-Hwan Lee            return;
2437231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
2438231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
2439fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            fis = mPendingFile.openRead();
244006485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
244106485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams                Log.v(TAG_FILE, "Reading " + mPendingFile.getBaseFile());
244206485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams            }
2443ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            XmlPullParser parser;
2444ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            parser = Xml.newPullParser();
2445fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            parser.setInput(fis, null);
2446ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams
2447fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            int eventType = parser.getEventType();
2448fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            while (eventType != XmlPullParser.START_TAG &&
2449fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    eventType != XmlPullParser.END_DOCUMENT) {
2450fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                eventType = parser.next();
2451231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2452ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            if (eventType == XmlPullParser.END_DOCUMENT) return; // Nothing to read.
2453360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2454ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            do {
2455fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                PendingOperation pop = null;
24568ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                if (eventType == XmlPullParser.START_TAG) {
24578ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    try {
245806485a7c6e3bbea1f427f345ac3a18b2346750e0Matthew Williams                        String tagName = parser.getName();
24598ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        if (parser.getDepth() == 1 && "op".equals(tagName)) {
24608ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            // Verify version.
24618ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            String versionString =
24628ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                    parser.getAttributeValue(null, XML_ATTR_VERSION);
24638ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            if (versionString == null ||
24648ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                    Integer.parseInt(versionString) != PENDING_OPERATION_VERSION) {
24658ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                Log.w(TAG, "Unknown pending operation version " + versionString);
24668ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                throw new java.io.IOException("Unknown version.");
24678ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            }
24688ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            int authorityId = Integer.valueOf(parser.getAttributeValue(
24698ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                    null, XML_ATTR_AUTHORITYID));
24708ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            boolean expedited = Boolean.valueOf(parser.getAttributeValue(
24718ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                    null, XML_ATTR_EXPEDITED));
24728ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            int syncSource = Integer.valueOf(parser.getAttributeValue(
24738ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                    null, XML_ATTR_SOURCE));
24748ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            int reason = Integer.valueOf(parser.getAttributeValue(
24758ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                    null, XML_ATTR_REASON));
24768ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            AuthorityInfo authority = mAuthorities.get(authorityId);
24778ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
24788ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                Log.v(TAG_FILE, authorityId + " " + expedited + " " + syncSource + " "
24798ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                        + reason);
24808ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            }
24818ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            if (authority != null) {
24828ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                pop = new PendingOperation(
24838ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                        authority, reason, syncSource, new Bundle(), expedited);
24848ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                pop.flatExtras = null; // No longer used.
24858ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                mPendingOperations.add(pop);
2486ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
24878ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                    Log.v(TAG_FILE, "Adding pending op: "
24888ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                            + pop.target
2489fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                                            + " src=" + pop.syncSource
2490fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                                            + " reason=" + pop.reason
2491fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                                            + " expedited=" + pop.expedited);
249256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                                    }
24938ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            } else {
24948ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                // Skip non-existent authority.
24958ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                pop = null;
24968ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
24978ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                    Log.v(TAG_FILE, "No authority found for " + authorityId
24988ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                            + ", skipping");
2499fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                                }
2500fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                            }
25018ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        } else if (parser.getDepth() == 2 &&
25028ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                pop != null &&
25038ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                                "extra".equals(tagName)) {
25048ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            parseExtra(parser, pop.extras);
2505fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                        }
25068ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                    } catch (NumberFormatException e) {
25078ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                        Log.d(TAG, "Invalid data in xml file.", e);
2508fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    }
25098ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                }
2510ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                eventType = parser.next();
2511ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            } while(eventType != XmlPullParser.END_DOCUMENT);
2512fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        } catch (java.io.IOException e) {
2513ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            Log.w(TAG_FILE, "Error reading pending data.", e);
2514ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        } catch (XmlPullParserException e) {
2515ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
2516ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                Log.w(TAG_FILE, "Error parsing pending ops xml.", e);
2517ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            }
2518fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        } finally {
2519fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            if (fis != null) {
2520fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                try {
2521fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                    fis.close();
2522fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                } catch (java.io.IOException e1) {}
2523231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2524231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
2525231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
2526ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams
252756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    static private byte[] flattenBundle(Bundle bundle) {
252856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        byte[] flatData = null;
252956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        Parcel parcel = Parcel.obtain();
253056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        try {
253156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            bundle.writeToParcel(parcel, 0);
253256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            flatData = parcel.marshall();
253356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } finally {
253456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            parcel.recycle();
253556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
253656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        return flatData;
253756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
253856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
253956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    static private Bundle unflattenBundle(byte[] flatData) {
254056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        Bundle bundle;
254156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        Parcel parcel = Parcel.obtain();
254256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        try {
254356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            parcel.unmarshall(flatData, 0, flatData.length);
254456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            parcel.setDataPosition(0);
254556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            bundle = parcel.readBundle();
254656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } catch (RuntimeException e) {
254756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            // A RuntimeException is thrown if we were unable to parse the parcel.
254856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            // Create an empty parcel in this case.
254956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            bundle = new Bundle();
255056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } finally {
255156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            parcel.recycle();
255256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
255356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        return bundle;
255456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
255556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
25568ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams    private static final String XML_ATTR_VERSION = "version";
2557ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    private static final String XML_ATTR_AUTHORITYID = "authority_id";
2558ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    private static final String XML_ATTR_SOURCE = "source";
2559ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    private static final String XML_ATTR_EXPEDITED = "expedited";
2560ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    private static final String XML_ATTR_REASON = "reason";
2561ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams
2562231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
2563ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams     * Write all currently pending ops to the pending ops file.
2564231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
2565ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams    private void writePendingOperationsLocked() {
2566ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        final int N = mPendingOperations.size();
2567ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        FileOutputStream fos = null;
2568ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        try {
2569ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            if (N == 0) {
257056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)){
257156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    Log.v(TAG, "Truncating " + mPendingFile.getBaseFile());
2572fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                }
2573ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                mPendingFile.truncate();
2574ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                return;
2575ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            }
2576ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
257756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                Log.v(TAG, "Writing new " + mPendingFile.getBaseFile());
2578ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            }
2579ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            fos = mPendingFile.startWrite();
2580ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            XmlSerializer out = new FastXmlSerializer();
2581ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            out.setOutput(fos, "utf-8");
2582ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams
2583ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            for (int i = 0; i < N; i++) {
2584ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                PendingOperation pop = mPendingOperations.get(i);
25858ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                writePendingOperationLocked(pop, out);
258656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams             }
258756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams             out.endDocument();
258856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams             mPendingFile.finishWrite(fos);
2589ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        } catch (java.io.IOException e1) {
2590ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            Log.w(TAG, "Error writing pending operations", e1);
2591ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            if (fos != null) {
2592ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams                mPendingFile.failWrite(fos);
25939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2594231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
2595231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
2596360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
25978ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams    /** Write all currently pending ops to the pending ops file. */
25988ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     private void writePendingOperationLocked(PendingOperation pop, XmlSerializer out)
25998ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams             throws IOException {
26008ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         // Pending operation.
26018ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         out.startTag(null, "op");
26028ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams
26038ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         out.attribute(null, XML_ATTR_VERSION, Integer.toString(PENDING_OPERATION_VERSION));
26048ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         out.attribute(null, XML_ATTR_AUTHORITYID, Integer.toString(pop.authorityId));
26058ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         out.attribute(null, XML_ATTR_SOURCE, Integer.toString(pop.syncSource));
26068ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         out.attribute(null, XML_ATTR_EXPEDITED, Boolean.toString(pop.expedited));
26078ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         out.attribute(null, XML_ATTR_REASON, Integer.toString(pop.reason));
26088ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         extrasToXml(out, pop.extras);
26098ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams
26108ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams         out.endTag(null, "op");
26118ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     }
26128ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams
26138ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams    /**
26148ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * Append the given operation to the pending ops file; if unable to,
26158ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     * write all pending ops.
26168ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams     */
26178ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams    private void appendPendingOperationLocked(PendingOperation op) {
26188ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
26198ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
26208ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        }
26218ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        FileOutputStream fos = null;
26228ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        try {
26238ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            fos = mPendingFile.openAppend();
26248ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        } catch (java.io.IOException e) {
26258ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
26268ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                Log.v(TAG, "Failed append; writing full file");
26278ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            }
26288ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            writePendingOperationsLocked();
26298ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            return;
26308ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        }
26318ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams
26328ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        try {
26338ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            XmlSerializer out = new FastXmlSerializer();
26348ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            out.setOutput(fos, "utf-8");
26358ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            writePendingOperationLocked(op, out);
26368ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            out.endDocument();
26378ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            mPendingFile.finishWrite(fos);
26388ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        } catch (java.io.IOException e1) {
26398ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            Log.w(TAG, "Error writing appending operation", e1);
26408ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            mPendingFile.failWrite(fos);
26418ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        } finally {
26428ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            try {
26438ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                fos.close();
26448ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            } catch (IOException e) {}
26458ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams        }
26468ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams    }
2647360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2648fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    private void extrasToXml(XmlSerializer out, Bundle extras) throws java.io.IOException {
2649fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        for (String key : extras.keySet()) {
2650fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            out.startTag(null, "extra");
2651fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            out.attribute(null, "name", key);
2652fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            final Object value = extras.get(key);
2653fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            if (value instanceof Long) {
2654fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "type", "long");
2655fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "value1", value.toString());
2656fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            } else if (value instanceof Integer) {
2657fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "type", "integer");
2658fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "value1", value.toString());
2659fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            } else if (value instanceof Boolean) {
2660fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "type", "boolean");
2661fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "value1", value.toString());
2662fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            } else if (value instanceof Float) {
2663fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "type", "float");
2664fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "value1", value.toString());
2665fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            } else if (value instanceof Double) {
2666fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "type", "double");
2667fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "value1", value.toString());
2668fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            } else if (value instanceof String) {
2669fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "type", "string");
2670fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "value1", value.toString());
2671fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            } else if (value instanceof Account) {
2672fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "type", "account");
2673fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "value1", ((Account)value).name);
2674fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                out.attribute(null, "value2", ((Account)value).type);
2675fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            }
2676fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams            out.endTag(null, "extra");
2677fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        }
2678fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    }
2679fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
268056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    private void requestSync(AuthorityInfo authorityInfo, int reason, Bundle extras) {
268156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        if (android.os.Process.myUid() == android.os.Process.SYSTEM_UID
268256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                && mSyncRequestListener != null) {
26838ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            mSyncRequestListener.onSyncRequest(authorityInfo.target, reason, extras);
268456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        } else {
268556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            SyncRequest.Builder req =
268656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                    new SyncRequest.Builder()
268769002ae2a2afd0f759c22ea47d669ddc33b3255aNick Kralevich                            .syncOnce()
26888ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                            .setExtras(extras);
26898ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            if (authorityInfo.target.target_provider) {
26908ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                req.setSyncAdapter(authorityInfo.target.account, authorityInfo.target.provider);
269156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            } else {
26925a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams                if (Log.isLoggable(TAG, Log.DEBUG)) {
26935a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams                    Log.d(TAG, "Unknown target, skipping sync request.");
26945a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams                }
26955a9decd589f3f6a512168fd669ee2c5d8daa238bMatthew Williams                return;
269656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            }
269756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            ContentResolver.requestSync(req.build());
269856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams        }
269956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams    }
270056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams
270157286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert    private void requestSync(Account account, int userId, int reason, String authority,
270257286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert            Bundle extras) {
270304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        // If this is happening in the system process, then call the syncrequest listener
270404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        // to make a request back to the SyncManager directly.
270504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        // If this is probably a test instance, then call back through the ContentResolver
270604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        // which will know which userId to apply based on the Binder id.
270704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        if (android.os.Process.myUid() == android.os.Process.SYSTEM_UID
270804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                && mSyncRequestListener != null) {
270956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams            mSyncRequestListener.onSyncRequest(
27108ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                new EndPoint(account, authority, userId),
27118ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                reason,
27128ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams                extras);
271304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        } else {
271404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            ContentResolver.requestSync(account, authority, extras);
271504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
271604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
271704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
2718231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_END = 0;
2719231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM_OLD = 100;
2720231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    public static final int STATISTICS_FILE_ITEM = 101;
2721360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2722231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
2723231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Read all sync statistics back in to the initial engine state.
2724231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
2725231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void readStatisticsLocked() {
2726231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
2727231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            byte[] data = mStatisticsFile.readFully();
2728231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel in = Parcel.obtain();
2729231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.unmarshall(data, 0, data.length);
2730231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            in.setDataPosition(0);
2731231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int token;
2732231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            int index = 0;
2733231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            while ((token=in.readInt()) != STATISTICS_FILE_END) {
2734231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (token == STATISTICS_FILE_ITEM
2735231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        || token == STATISTICS_FILE_ITEM_OLD) {
2736231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    int day = in.readInt();
2737231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (token == STATISTICS_FILE_ITEM_OLD) {
2738231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        day = day - 2009 + 14245;  // Magic!
2739231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
2740231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    DayStats ds = new DayStats(day);
2741231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successCount = in.readInt();
2742231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.successTime = in.readLong();
2743231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureCount = in.readInt();
2744231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    ds.failureTime = in.readLong();
2745231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    if (index < mDayStats.length) {
2746231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        mDayStats[index] = ds;
2747231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                        index++;
2748231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    }
2749231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                } else {
2750231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    // Ooops.
2751231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    Log.w(TAG, "Unknown stats token: " + token);
2752231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
2753231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
2754231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2755231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e) {
2756231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.i(TAG, "No initial statistics");
2757231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        }
2758231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    }
2759360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2760231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    /**
2761231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     * Write all sync statistics to the sync status file.
2762231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn     */
2763231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn    private void writeStatisticsLocked() {
2764ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
2765ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams            Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
2766ba35271e91648c9cde2bb606aaf2001282231b07Matthew Williams        }
2767360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2768231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // The file is being written, so we don't need to have a scheduled
2769231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        // write until the next change.
2770231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        removeMessages(MSG_WRITE_STATISTICS);
2771360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2772231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        FileOutputStream fos = null;
2773231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        try {
2774231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos = mStatisticsFile.startWrite();
2775231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Parcel out = Parcel.obtain();
2776231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            final int N = mDayStats.length;
2777231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            for (int i=0; i<N; i++) {
2778231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                DayStats ds = mDayStats[i];
2779231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                if (ds == null) {
2780231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                    break;
2781231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                }
2782231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(STATISTICS_FILE_ITEM);
2783231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.day);
2784231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.successCount);
2785231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.successTime);
2786231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeInt(ds.failureCount);
2787231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                out.writeLong(ds.failureTime);
2788231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
2789231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.writeInt(STATISTICS_FILE_END);
2790231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            fos.write(out.marshall());
2791231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            out.recycle();
2792360e454b2b2f911e9e29268519017cc94ae9d4f4Costin Manolache
2793231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            mStatisticsFile.finishWrite(fos);
2794231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn        } catch (java.io.IOException e1) {
2795231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            Log.w(TAG, "Error writing stats", e1);
2796231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            if (fos != null) {
2797231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn                mStatisticsFile.failWrite(fos);
2798231cc608d06ffc31c24bf8aa8c8275bdd2636581Dianne Hackborn            }
27999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
28009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2801fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams
2802fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    /**
2803fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     * Dump state of PendingOperations.
2804fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams     */
2805fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    public void dumpPendingOperations(StringBuilder sb) {
2806fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        sb.append("Pending Ops: ").append(mPendingOperations.size()).append(" operation(s)\n");
2807fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        for (PendingOperation pop : mPendingOperations) {
28088ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams            sb.append("(info: " + pop.target.toString())
280956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams                .append(", extras: " + pop.extras)
2810fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams                .append(")\n");
2811fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams        }
2812fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams    }
28139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2814