diff options
author | Dianne Hackborn <hackbod@google.com> | 2009-05-06 00:28:37 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2009-05-06 00:28:37 -0700 |
commit | 7a1355950172b7a549820e9a2cd4a9b2099ec32f (patch) | |
tree | dc8940cdf38bae09e3427e44ebf1328861abc20b /core/java/android/content/SyncManager.java | |
parent | 39a8bb26326ceeaad5b46d29bf485329c67ced2f (diff) | |
parent | 231cc608d06ffc31c24bf8aa8c8275bdd2636581 (diff) | |
download | frameworks_base-7a1355950172b7a549820e9a2cd4a9b2099ec32f.zip frameworks_base-7a1355950172b7a549820e9a2cd4a9b2099ec32f.tar.gz frameworks_base-7a1355950172b7a549820e9a2cd4a9b2099ec32f.tar.bz2 |
merged 231cc608d06ffc31c24bf8aa8c8275bdd2636581
Diffstat (limited to 'core/java/android/content/SyncManager.java')
-rw-r--r-- | core/java/android/content/SyncManager.java | 663 |
1 files changed, 322 insertions, 341 deletions
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index 9bf41c7..019abb8 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -44,7 +44,6 @@ import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.Parcel; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; @@ -54,6 +53,7 @@ import android.os.SystemProperties; import android.provider.Sync; import android.provider.Settings; import android.provider.Sync.History; +import android.text.TextUtils; import android.text.format.DateUtils; import android.text.format.Time; import android.util.Config; @@ -69,7 +69,9 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -78,7 +80,6 @@ import java.util.Random; import java.util.Observer; import java.util.Observable; import java.util.Set; -import java.util.HashSet; /** * @hide @@ -134,7 +135,6 @@ class SyncManager implements OnAccountsUpdatedListener { volatile private PowerManager.WakeLock mHandleAlarmWakeLock; volatile private boolean mDataConnectionIsConnected = false; volatile private boolean mStorageIsLow = false; - private Sync.Settings.QueryMap mSyncSettings; private final NotificationManager mNotificationMgr; private AlarmManager mAlarmService = null; @@ -259,17 +259,6 @@ class SyncManager implements OnAccountsUpdatedListener { private static final String SYNC_POLL_ALARM = "android.content.syncmanager.SYNC_POLL_ALARM"; private final SyncHandler mSyncHandler; - private static final String[] SYNC_ACTIVE_PROJECTION = new String[]{ - Sync.Active.ACCOUNT, - Sync.Active.AUTHORITY, - Sync.Active.START_TIME, - }; - - private static final String[] SYNC_PENDING_PROJECTION = new String[]{ - Sync.Pending.ACCOUNT, - Sync.Pending.AUTHORITY - }; - private static final int MAX_SYNC_POLL_DELAY_SECONDS = 36 * 60 * 60; // 36 hours private static final int MIN_SYNC_POLL_DELAY_SECONDS = 24 * 60 * 60; // 24 hours @@ -331,6 +320,14 @@ class SyncManager implements OnAccountsUpdatedListener { mHandleAlarmWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, HANDLE_SYNC_ALARM_WAKE_LOCK); mHandleAlarmWakeLock.setReferenceCounted(false); + + mSyncStorageEngine.addStatusChangeListener( + SyncStorageEngine.CHANGE_SETTINGS, new ISyncStatusObserver.Stub() { + public void onStatusChanged(int which) { + // force the sync loop to run if the settings change + sendCheckAlarmsMessage(); + } + }); } private synchronized void initializeSyncPoll() { @@ -455,20 +452,10 @@ class SyncManager implements OnAccountsUpdatedListener { return mActiveSyncContext; } - private Sync.Settings.QueryMap getSyncSettings() { - if (mSyncSettings == null) { - mSyncSettings = new Sync.Settings.QueryMap(mContext.getContentResolver(), true, - new Handler()); - mSyncSettings.addObserver(new Observer(){ - public void update(Observable o, Object arg) { - // force the sync loop to run if the settings change - sendCheckAlarmsMessage(); - } - }); - } - return mSyncSettings; + public SyncStorageEngine getSyncStorageEngine() { + return mSyncStorageEngine; } - + private void ensureAlarmService() { if (mAlarmService == null) { mAlarmService = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); @@ -575,15 +562,15 @@ class SyncManager implements OnAccountsUpdatedListener { int source; if (uploadOnly) { - source = Sync.History.SOURCE_LOCAL; + source = SyncStorageEngine.SOURCE_LOCAL; } else if (force) { - source = Sync.History.SOURCE_USER; + source = SyncStorageEngine.SOURCE_USER; } else if (url == null) { - source = Sync.History.SOURCE_POLL; + source = SyncStorageEngine.SOURCE_POLL; } else { // this isn't strictly server, since arbitrary callers can (and do) request // a non-forced two-way sync on a specific url - source = Sync.History.SOURCE_SERVER; + source = SyncStorageEngine.SOURCE_SERVER; } // compile a list of authorities that have sync adapters @@ -655,8 +642,7 @@ class SyncManager implements OnAccountsUpdatedListener { public void updateHeartbeatTime() { mHeartbeatTime = SystemClock.elapsedRealtime(); - mContext.getContentResolver().notifyChange(Sync.Active.CONTENT_URI, - null /* this change wasn't made through an observer */); + mSyncStorageEngine.reportActiveChange(); } private void sendSyncAlarmMessage() { @@ -862,7 +848,7 @@ class SyncManager implements OnAccountsUpdatedListener { final String key; long earliestRunTime; long delay; - Long rowId = null; + SyncStorageEngine.PendingOperation pendingOperation; SyncOperation(Account account, int source, String authority, Bundle extras, long delay) { this.account = account; @@ -902,7 +888,7 @@ class SyncManager implements OnAccountsUpdatedListener { sb.append(" when: ").append(earliestRunTime); sb.append(" delay: ").append(delay); sb.append(" key: {").append(key).append("}"); - if (rowId != null) sb.append(" rowId: ").append(rowId); + if (pendingOperation != null) sb.append(" pendingOperation: ").append(pendingOperation); return sb.toString(); } @@ -1014,251 +1000,278 @@ class SyncManager implements OnAccountsUpdatedListener { protected void dump(FileDescriptor fd, PrintWriter pw) { StringBuilder sb = new StringBuilder(); - dumpSyncState(sb); - sb.append("\n"); + dumpSyncState(pw, sb); if (isSyncEnabled()) { - dumpSyncHistory(sb); + dumpSyncHistory(pw, sb); } - pw.println(sb.toString()); + pw.println(); pw.println("SyncAdapters:"); for (RegisteredServicesCache.ServiceInfo info : mSyncAdapters.getAllServices()) { pw.println(" " + info); } } - protected void dumpSyncState(StringBuilder sb) { - sb.append("sync enabled: ").append(isSyncEnabled()).append("\n"); - sb.append("data connected: ").append(mDataConnectionIsConnected).append("\n"); - sb.append("memory low: ").append(mStorageIsLow).append("\n"); + static String formatTime(long time) { + Time tobj = new Time(); + tobj.set(time); + return tobj.format("%Y-%m-%d %H:%M:%S"); + } + + protected void dumpSyncState(PrintWriter pw, StringBuilder sb) { + pw.print("sync enabled: "); pw.println(isSyncEnabled()); + pw.print("data connected: "); pw.println(mDataConnectionIsConnected); + pw.print("memory low: "); pw.println(mStorageIsLow); final Account[] accounts = mAccounts; - sb.append("accounts: "); + pw.print("accounts: "); if (accounts != null) { - sb.append(accounts.length); + pw.println(accounts.length); } else { - sb.append("none"); + pw.println("none"); } - sb.append("\n"); final long now = SystemClock.elapsedRealtime(); - sb.append("now: ").append(now).append("\n"); - sb.append("uptime: ").append(DateUtils.formatElapsedTime(now/1000)).append(" (HH:MM:SS)\n"); - sb.append("time spent syncing : ") - .append(DateUtils.formatElapsedTime( - mSyncHandler.mSyncTimeTracker.timeSpentSyncing() / 1000)) - .append(" (HH:MM:SS), sync ") - .append(mSyncHandler.mSyncTimeTracker.mLastWasSyncing ? "" : "not ") - .append("in progress").append("\n"); + pw.print("now: "); pw.println(now); + pw.print("uptime: "); pw.print(DateUtils.formatElapsedTime(now/1000)); + pw.println(" (HH:MM:SS)"); + pw.print("time spent syncing: "); + pw.print(DateUtils.formatElapsedTime( + mSyncHandler.mSyncTimeTracker.timeSpentSyncing() / 1000)); + pw.print(" (HH:MM:SS), sync "); + pw.print(mSyncHandler.mSyncTimeTracker.mLastWasSyncing ? "" : "not "); + pw.println("in progress"); if (mSyncHandler.mAlarmScheduleTime != null) { - sb.append("next alarm time: ").append(mSyncHandler.mAlarmScheduleTime) - .append(" (") - .append(DateUtils.formatElapsedTime((mSyncHandler.mAlarmScheduleTime-now)/1000)) - .append(" (HH:MM:SS) from now)\n"); + pw.print("next alarm time: "); pw.print(mSyncHandler.mAlarmScheduleTime); + pw.print(" ("); + pw.print(DateUtils.formatElapsedTime((mSyncHandler.mAlarmScheduleTime-now)/1000)); + pw.println(" (HH:MM:SS) from now)"); } else { - sb.append("no alarm is scheduled (there had better not be any pending syncs)\n"); + pw.println("no alarm is scheduled (there had better not be any pending syncs)"); } - sb.append("active sync: ").append(mActiveSyncContext).append("\n"); + pw.print("active sync: "); pw.println(mActiveSyncContext); - sb.append("notification info: "); + pw.print("notification info: "); + sb.setLength(0); mSyncHandler.mSyncNotificationInfo.toString(sb); - sb.append("\n"); + pw.println(sb.toString()); synchronized (mSyncQueue) { - sb.append("sync queue: "); + pw.print("sync queue: "); + sb.setLength(0); mSyncQueue.dump(sb); - } - - Cursor c = mSyncStorageEngine.query(Sync.Active.CONTENT_URI, - SYNC_ACTIVE_PROJECTION, null, null, null); - sb.append("\n"); - try { - if (c.moveToNext()) { - final long durationInSeconds = (now - c.getLong(2)) / 1000; - sb.append("Active sync: ").append(c.getString(0)) - .append(" ").append(c.getString(1)) - .append(", duration is ") - .append(DateUtils.formatElapsedTime(durationInSeconds)).append(".\n"); - } else { - sb.append("No sync is in progress.\n"); - } - } finally { - c.close(); - } - - c = mSyncStorageEngine.query(Sync.Pending.CONTENT_URI, - SYNC_PENDING_PROJECTION, null, null, "account, authority"); - sb.append("\nPending Syncs\n"); - try { - if (c.getCount() != 0) { - dumpSyncPendingHeader(sb); - while (c.moveToNext()) { - dumpSyncPendingRow(sb, c); + pw.println(sb.toString()); + } + + ActiveSyncInfo active = mSyncStorageEngine.getActiveSync(); + if (active != null) { + SyncStorageEngine.AuthorityInfo authority + = mSyncStorageEngine.getAuthority(active.authorityId); + final long durationInSeconds = (now - active.startTime) / 1000; + pw.print("Active sync: "); + pw.print(authority != null ? authority.account : "<no account>"); + pw.print(" "); + pw.print(authority != null ? authority.authority : "<no account>"); + pw.print(", duration is "); + pw.println(DateUtils.formatElapsedTime(durationInSeconds)); + } else { + pw.println("No sync is in progress."); + } + + ArrayList<SyncStorageEngine.PendingOperation> ops + = mSyncStorageEngine.getPendingOperations(); + if (ops != null && ops.size() > 0) { + pw.println(); + pw.println("Pending Syncs"); + final int N = ops.size(); + for (int i=0; i<N; i++) { + SyncStorageEngine.PendingOperation op = ops.get(i); + pw.print(" #"); pw.print(i); pw.print(": account="); + pw.print(op.account.mName); pw.print(":"); + pw.print(op.account.mType); pw.print(" authority="); + pw.println(op.authority); + if (op.extras != null && op.extras.size() > 0) { + sb.setLength(0); + SyncOperation.extrasToStringBuilder(op.extras, sb); + pw.print(" extras: "); pw.println(sb.toString()); } - dumpSyncPendingFooter(sb); - } else { - sb.append("none\n"); } - } finally { - c.close(); } - Account currentAccount = null; - c = mSyncStorageEngine.query(Sync.Status.CONTENT_URI, - STATUS_PROJECTION, null, null, "account_type, account, authority"); - sb.append("\nSync history by account and authority\n"); - try { - while (c.moveToNext()) { - final Account account = new Account(c.getString(0), c.getString(13)); - if (!account.equals(currentAccount)) { - if (currentAccount != null) { - dumpSyncHistoryFooter(sb); + HashSet<Account> processedAccounts = new HashSet<Account>(); + ArrayList<SyncStatusInfo> statuses + = mSyncStorageEngine.getSyncStatus(); + if (statuses != null && statuses.size() > 0) { + pw.println(); + pw.println("Sync Status"); + final int N = statuses.size(); + for (int i=0; i<N; i++) { + SyncStatusInfo status = statuses.get(i); + SyncStorageEngine.AuthorityInfo authority + = mSyncStorageEngine.getAuthority(status.authorityId); + if (authority != null) { + Account curAccount = authority.account; + + if (processedAccounts.contains(curAccount)) { + continue; + } + + processedAccounts.add(curAccount); + + pw.print(" Account "); pw.print(authority.account.mName); + pw.print(" "); pw.print(authority.account.mType); + pw.println(":"); + for (int j=i; j<N; j++) { + status = statuses.get(j); + authority = mSyncStorageEngine.getAuthority(status.authorityId); + if (!curAccount.equals(authority.account)) { + continue; + } + pw.print(" "); pw.print(authority.authority); + pw.println(":"); + pw.print(" count: local="); pw.print(status.numSourceLocal); + pw.print(" poll="); pw.print(status.numSourcePoll); + pw.print(" server="); pw.print(status.numSourceServer); + pw.print(" user="); pw.print(status.numSourceUser); + pw.print(" total="); pw.println(status.numSyncs); + pw.print(" total duration: "); + pw.println(DateUtils.formatElapsedTime( + status.totalElapsedTime/1000)); + if (status.lastSuccessTime != 0) { + pw.print(" SUCCESS: source="); + pw.print(SyncStorageEngine.SOURCES[ + status.lastSuccessSource]); + pw.print(" time="); + pw.println(formatTime(status.lastSuccessTime)); + } else { + pw.print(" FAILURE: source="); + pw.print(SyncStorageEngine.SOURCES[ + status.lastFailureSource]); + pw.print(" initialTime="); + pw.print(formatTime(status.initialFailureTime)); + pw.print(" lastTime="); + pw.println(formatTime(status.lastFailureTime)); + pw.print(" message: "); pw.println(status.lastFailureMesg); + } } - currentAccount = account; - dumpSyncHistoryHeader(sb, currentAccount); } - - dumpSyncHistoryRow(sb, c); } - if (c.getCount() > 0) dumpSyncHistoryFooter(sb); - } finally { - c.close(); } } - private void dumpSyncHistoryHeader(StringBuilder sb, Account account) { - sb.append(" ").append(account).append("\n"); - sb.append(" ___________________________________________________________________________________________________________________________\n"); - sb.append(" | | num times synced | total | last success | |\n"); - sb.append(" | authority | local | poll | server | user | total | duration | source | time | result if failing |\n"); + private void dumpTimeSec(PrintWriter pw, long time) { + pw.print(time/1000); pw.print('.'); pw.print((time/100)%10); + pw.print('s'); } - - private static String[] STATUS_PROJECTION = new String[]{ - Sync.Status.ACCOUNT, // 0 - Sync.Status.AUTHORITY, // 1 - Sync.Status.NUM_SYNCS, // 2 - Sync.Status.TOTAL_ELAPSED_TIME, // 3 - Sync.Status.NUM_SOURCE_LOCAL, // 4 - Sync.Status.NUM_SOURCE_POLL, // 5 - Sync.Status.NUM_SOURCE_SERVER, // 6 - Sync.Status.NUM_SOURCE_USER, // 7 - Sync.Status.LAST_SUCCESS_SOURCE, // 8 - Sync.Status.LAST_SUCCESS_TIME, // 9 - Sync.Status.LAST_FAILURE_SOURCE, // 10 - Sync.Status.LAST_FAILURE_TIME, // 11 - Sync.Status.LAST_FAILURE_MESG, // 12 - Sync.Status.ACCOUNT_TYPE, // 13 - }; - - private void dumpSyncHistoryRow(StringBuilder sb, Cursor c) { - boolean hasSuccess = !c.isNull(9); - boolean hasFailure = !c.isNull(11); - Time timeSuccess = new Time(); - if (hasSuccess) timeSuccess.set(c.getLong(9)); - Time timeFailure = new Time(); - if (hasFailure) timeFailure.set(c.getLong(11)); - sb.append(String.format(" | %-15s | %5d | %5d | %6d | %5d | %5d | %8s | %7s | %19s | %19s |\n", - c.getString(1), - c.getLong(4), - c.getLong(5), - c.getLong(6), - c.getLong(7), - c.getLong(2), - DateUtils.formatElapsedTime(c.getLong(3)/1000), - hasSuccess ? Sync.History.SOURCES[c.getInt(8)] : "", - hasSuccess ? timeSuccess.format("%Y-%m-%d %H:%M:%S") : "", - hasFailure ? History.mesgToString(c.getString(12)) : "")); + + private void dumpDayStatistic(PrintWriter pw, SyncStorageEngine.DayStats ds) { + pw.print("Success ("); pw.print(ds.successCount); + if (ds.successCount > 0) { + pw.print(" for "); dumpTimeSec(pw, ds.successTime); + pw.print(" avg="); dumpTimeSec(pw, ds.successTime/ds.successCount); + } + pw.print(") Failure ("); pw.print(ds.failureCount); + if (ds.failureCount > 0) { + pw.print(" for "); dumpTimeSec(pw, ds.failureTime); + pw.print(" avg="); dumpTimeSec(pw, ds.failureTime/ds.failureCount); + } + pw.println(")"); } - - private void dumpSyncHistoryFooter(StringBuilder sb) { - sb.append(" |___________________________________________________________________________________________________________________________|\n"); - } - - private void dumpSyncPendingHeader(StringBuilder sb) { - sb.append(" ____________________________________________________\n"); - sb.append(" | account | authority |\n"); - } - - private void dumpSyncPendingRow(StringBuilder sb, Cursor c) { - sb.append(String.format(" | %-30s | %-15s |\n", c.getString(0), c.getString(1))); - } - - private void dumpSyncPendingFooter(StringBuilder sb) { - sb.append(" |__________________________________________________|\n"); - } - - protected void dumpSyncHistory(StringBuilder sb) { - Cursor c = mSyncStorageEngine.query(Sync.History.CONTENT_URI, null, "event=?", - new String[]{String.valueOf(Sync.History.EVENT_STOP)}, - Sync.HistoryColumns.EVENT_TIME + " desc"); - try { - long numSyncsLastHour = 0, durationLastHour = 0; - long numSyncsLastDay = 0, durationLastDay = 0; - long numSyncsLastWeek = 0, durationLastWeek = 0; - long numSyncsLast4Weeks = 0, durationLast4Weeks = 0; - long numSyncsTotal = 0, durationTotal = 0; - - long now = System.currentTimeMillis(); - int indexEventTime = c.getColumnIndexOrThrow(Sync.History.EVENT_TIME); - int indexElapsedTime = c.getColumnIndexOrThrow(Sync.History.ELAPSED_TIME); - while (c.moveToNext()) { - long duration = c.getLong(indexElapsedTime); - long endTime = c.getLong(indexEventTime) + duration; - long millisSinceStart = now - endTime; - numSyncsTotal++; - durationTotal += duration; - if (millisSinceStart < MILLIS_IN_HOUR) { - numSyncsLastHour++; - durationLastHour += duration; + + protected void dumpSyncHistory(PrintWriter pw, StringBuilder sb) { + SyncStorageEngine.DayStats dses[] = mSyncStorageEngine.getDayStatistics(); + if (dses != null && dses[0] != null) { + pw.println(); + pw.println("Sync Statistics"); + pw.print(" Today: "); dumpDayStatistic(pw, dses[0]); + int today = dses[0].day; + int i; + SyncStorageEngine.DayStats ds; + + // Print each day in the current week. + for (i=1; i<=6 && i < dses.length; i++) { + ds = dses[i]; + if (ds == null) break; + int delta = today-ds.day; + if (delta > 6) break; + + pw.print(" Day-"); pw.print(delta); pw.print(": "); + dumpDayStatistic(pw, ds); + } + + // Aggregate all following days into weeks and print totals. + int weekDay = today; + while (i < dses.length) { + SyncStorageEngine.DayStats aggr = null; + weekDay -= 7; + while (i < dses.length) { + ds = dses[i]; + if (ds == null) { + i = dses.length; + break; + } + int delta = weekDay-ds.day; + if (delta > 6) break; + i++; + + if (aggr == null) { + aggr = new SyncStorageEngine.DayStats(weekDay); + } + aggr.successCount += ds.successCount; + aggr.successTime += ds.successTime; + aggr.failureCount += ds.failureCount; + aggr.failureTime += ds.failureTime; } - if (millisSinceStart < MILLIS_IN_DAY) { - numSyncsLastDay++; - durationLastDay += duration; + if (aggr != null) { + pw.print(" Week-"); pw.print((today-weekDay)/7); pw.print(": "); + dumpDayStatistic(pw, aggr); } - if (millisSinceStart < MILLIS_IN_WEEK) { - numSyncsLastWeek++; - durationLastWeek += duration; + } + } + + ArrayList<SyncStorageEngine.SyncHistoryItem> items + = mSyncStorageEngine.getSyncHistory(); + if (items != null && items.size() > 0) { + pw.println(); + pw.println("Recent Sync History"); + final int N = items.size(); + for (int i=0; i<N; i++) { + SyncStorageEngine.SyncHistoryItem item = items.get(i); + SyncStorageEngine.AuthorityInfo authority + = mSyncStorageEngine.getAuthority(item.authorityId); + pw.print(" #"); pw.print(i+1); pw.print(": "); + if (authority != null) { + pw.print(authority.account.mName); + pw.print(":"); + pw.print(authority.account.mType); + pw.print(" "); + pw.print(authority.authority); + } else { + pw.print("<no account>"); + } + Time time = new Time(); + time.set(item.eventTime); + pw.print(" "); pw.print(SyncStorageEngine.SOURCES[item.source]); + pw.print(" @ "); + pw.print(formatTime(item.eventTime)); + pw.print(" for "); + dumpTimeSec(pw, item.elapsedTime); + pw.println(); + if (item.event != SyncStorageEngine.EVENT_STOP + || item.upstreamActivity !=0 + || item.downstreamActivity != 0) { + pw.print(" event="); pw.print(item.event); + pw.print(" upstreamActivity="); pw.print(item.upstreamActivity); + pw.print(" downstreamActivity="); pw.println(item.downstreamActivity); } - if (millisSinceStart < MILLIS_IN_4WEEKS) { - numSyncsLast4Weeks++; - durationLast4Weeks += duration; + if (item.mesg != null + && !SyncStorageEngine.MESG_SUCCESS.equals(item.mesg)) { + pw.print(" mesg="); pw.println(item.mesg); } } - dumpSyncIntervalHeader(sb); - dumpSyncInterval(sb, "hour", MILLIS_IN_HOUR, numSyncsLastHour, durationLastHour); - dumpSyncInterval(sb, "day", MILLIS_IN_DAY, numSyncsLastDay, durationLastDay); - dumpSyncInterval(sb, "week", MILLIS_IN_WEEK, numSyncsLastWeek, durationLastWeek); - dumpSyncInterval(sb, "4 weeks", - MILLIS_IN_4WEEKS, numSyncsLast4Weeks, durationLast4Weeks); - dumpSyncInterval(sb, "total", 0, numSyncsTotal, durationTotal); - dumpSyncIntervalFooter(sb); - } finally { - c.close(); } } - private void dumpSyncIntervalHeader(StringBuilder sb) { - sb.append("Sync Stats\n"); - sb.append(" ___________________________________________________________\n"); - sb.append(" | | | duration in sec | |\n"); - sb.append(" | interval | count | average | total | % of interval |\n"); - } - - private void dumpSyncInterval(StringBuilder sb, String label, - long interval, long numSyncs, long duration) { - sb.append(String.format(" | %-8s | %6d | %8.1f | %8.1f", - label, numSyncs, ((float)duration/numSyncs)/1000, (float)duration/1000)); - if (interval > 0) { - sb.append(String.format(" | %13.2f |\n", ((float)duration/interval)*100.0)); - } else { - sb.append(String.format(" | %13s |\n", "na")); - } - } - - private void dumpSyncIntervalFooter(StringBuilder sb) { - sb.append(" |_________________________________________________________|\n"); - } - /** * A helper object to keep track of the time we have spent syncing since the last boot */ @@ -1541,7 +1554,6 @@ class SyncManager implements OnAccountsUpdatedListener { // found that is runnable (not disabled, etc). If that one is ready to run then // start it, otherwise just get out. SyncOperation syncOperation; - final Sync.Settings.QueryMap syncSettings = getSyncSettings(); final ConnectivityManager connManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); final boolean backgroundDataSetting = connManager.getBackgroundDataSetting(); @@ -1568,9 +1580,9 @@ class SyncManager implements OnAccountsUpdatedListener { final boolean force = syncOperation.extras.getBoolean( ContentResolver.SYNC_EXTRAS_FORCE, false); if (!force && (!backgroundDataSetting - || !syncSettings.getListenForNetworkTickles() - || !syncSettings.getSyncProviderAutomatically( - syncOperation.authority))) { + || !mSyncStorageEngine.getListenForNetworkTickles() + || !mSyncStorageEngine.getSyncProviderAutomatically( + null, syncOperation.authority))) { if (isLoggable) { Log.v(TAG, "runStateIdle: sync off, dropping " + syncOperation); } @@ -1697,7 +1709,7 @@ class SyncManager implements OnAccountsUpdatedListener { if (isLoggable) { Log.v(TAG, "finished sync operation " + syncOperation); } - historyMessage = History.MESG_SUCCESS; + historyMessage = SyncStorageEngine.MESG_SUCCESS; // TODO: set these correctly when the SyncResult is extended to include it downstreamActivity = 0; upstreamActivity = 0; @@ -1723,7 +1735,7 @@ class SyncManager implements OnAccountsUpdatedListener { // we don't need to retry this in this case } } - historyMessage = History.MESG_CANCELED; + historyMessage = SyncStorageEngine.MESG_CANCELED; downstreamActivity = 0; upstreamActivity = 0; } @@ -1758,14 +1770,22 @@ class SyncManager implements OnAccountsUpdatedListener { * If SyncResult.error() is true then it is safe to call this. */ private int syncResultToErrorNumber(SyncResult syncResult) { - if (syncResult.syncAlreadyInProgress) return History.ERROR_SYNC_ALREADY_IN_PROGRESS; - if (syncResult.stats.numAuthExceptions > 0) return History.ERROR_AUTHENTICATION; - if (syncResult.stats.numIoExceptions > 0) return History.ERROR_IO; - if (syncResult.stats.numParseExceptions > 0) return History.ERROR_PARSE; - if (syncResult.stats.numConflictDetectedExceptions > 0) return History.ERROR_CONFLICT; - if (syncResult.tooManyDeletions) return History.ERROR_TOO_MANY_DELETIONS; - if (syncResult.tooManyRetries) return History.ERROR_TOO_MANY_RETRIES; - if (syncResult.databaseError) return History.ERROR_INTERNAL; + if (syncResult.syncAlreadyInProgress) + return SyncStorageEngine.ERROR_SYNC_ALREADY_IN_PROGRESS; + if (syncResult.stats.numAuthExceptions > 0) + return SyncStorageEngine.ERROR_AUTHENTICATION; + if (syncResult.stats.numIoExceptions > 0) + return SyncStorageEngine.ERROR_IO; + if (syncResult.stats.numParseExceptions > 0) + return SyncStorageEngine.ERROR_PARSE; + if (syncResult.stats.numConflictDetectedExceptions > 0) + return SyncStorageEngine.ERROR_CONFLICT; + if (syncResult.tooManyDeletions) + return SyncStorageEngine.ERROR_TOO_MANY_DELETIONS; + if (syncResult.tooManyRetries) + return SyncStorageEngine.ERROR_TOO_MANY_RETRIES; + if (syncResult.databaseError) + return SyncStorageEngine.ERROR_INTERNAL; throw new IllegalStateException("we are not in an error state, " + syncResult); } @@ -1987,7 +2007,8 @@ class SyncManager implements OnAccountsUpdatedListener { final int source = syncOperation.syncSource; final long now = System.currentTimeMillis(); - EventLog.writeEvent(2720, syncOperation.authority, Sync.History.EVENT_START, source); + EventLog.writeEvent(2720, syncOperation.authority, + SyncStorageEngine.EVENT_START, source); return mSyncStorageEngine.insertStartSyncEvent( syncOperation.account, syncOperation.authority, now, source); @@ -1995,7 +2016,8 @@ class SyncManager implements OnAccountsUpdatedListener { public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage, int upstreamActivity, int downstreamActivity, long elapsedTime) { - EventLog.writeEvent(2720, syncOperation.authority, Sync.History.EVENT_STOP, syncOperation.syncSource); + EventLog.writeEvent(2720, syncOperation.authority, + SyncStorageEngine.EVENT_STOP, syncOperation.syncSource); mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime, resultMessage, downstreamActivity, upstreamActivity); @@ -2004,20 +2026,6 @@ class SyncManager implements OnAccountsUpdatedListener { static class SyncQueue { private SyncStorageEngine mSyncStorageEngine; - private final String[] COLUMNS = new String[]{ - "_id", - "authority", - "account", - "account_type", - "extras", - "source", - }; - private static final int COLUMN_ID = 0; - private static final int COLUMN_AUTHORITY = 1; - private static final int COLUMN_ACCOUNT = 2; - private static final int COLUMN_ACCOUNT_TYPE = 3; - private static final int COLUMN_EXTRAS = 4; - private static final int COLUMN_SOURCE = 5; private static final boolean DEBUG_CHECK_DATA_CONSISTENCY = false; @@ -2031,25 +2039,28 @@ class SyncManager implements OnAccountsUpdatedListener { public SyncQueue(SyncStorageEngine syncStorageEngine) { mSyncStorageEngine = syncStorageEngine; - Cursor cursor = mSyncStorageEngine.getPendingSyncsCursor(COLUMNS); - try { - while (cursor.moveToNext()) { - add(cursorToOperation(cursor), - true /* this is being added from the database */); - } - } finally { - cursor.close(); - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); - } + ArrayList<SyncStorageEngine.PendingOperation> ops + = mSyncStorageEngine.getPendingOperations(); + final int N = ops.size(); + for (int i=0; i<N; i++) { + SyncStorageEngine.PendingOperation op = ops.get(i); + SyncOperation syncOperation = new SyncOperation( + op.account, op.syncSource, op.authority, op.extras, 0); + syncOperation.pendingOperation = op; + add(syncOperation, op); + } + + if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(true /* check the DB */); } public boolean add(SyncOperation operation) { return add(new SyncOperation(operation), - false /* this is not coming from the database */); + null /* this is not coming from the database */); } - private boolean add(SyncOperation operation, boolean fromDatabase) { - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(!fromDatabase); + private boolean add(SyncOperation operation, + SyncStorageEngine.PendingOperation pop) { + if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(pop == null); // If this operation is expedited then set its earliestRunTime to be immediately // before the head of the list, or not if none are in the list. @@ -2081,7 +2092,7 @@ class SyncManager implements OnAccountsUpdatedListener { if (existingOperation != null && operation.earliestRunTime >= existingOperation.earliestRunTime) { - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(!fromDatabase); + if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(pop == null); return false; } @@ -2089,27 +2100,17 @@ class SyncManager implements OnAccountsUpdatedListener { removeByKey(operationKey); } - if (operation.rowId == null) { - byte[] extrasData = null; - Parcel parcel = Parcel.obtain(); - try { - operation.extras.writeToParcel(parcel, 0); - extrasData = parcel.marshall(); - } finally { - parcel.recycle(); - } - ContentValues values = new ContentValues(); - values.put("account", operation.account.mName); - values.put("account_type", operation.account.mType); - values.put("authority", operation.authority); - values.put("source", operation.syncSource); - values.put("extras", extrasData); - Uri pendingUri = mSyncStorageEngine.insertIntoPending(values); - operation.rowId = pendingUri == null ? null : ContentUris.parseId(pendingUri); - if (operation.rowId == null) { + operation.pendingOperation = pop; + if (operation.pendingOperation == null) { + pop = new SyncStorageEngine.PendingOperation( + operation.account, operation.syncSource, + operation.authority, operation.extras); + pop = mSyncStorageEngine.insertIntoPending(pop); + if (pop == null) { throw new IllegalStateException("error adding pending sync operation " + operation); } + operation.pendingOperation = pop; } if (DEBUG_CHECK_DATA_CONSISTENCY) { @@ -2119,7 +2120,7 @@ class SyncManager implements OnAccountsUpdatedListener { } mOpsByKey.put(operationKey, operation); mOpsByWhen.add(operation); - if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(!fromDatabase); + if (DEBUG_CHECK_DATA_CONSISTENCY) debugCheckDataStructures(pop == null); return true; } @@ -2131,7 +2132,7 @@ class SyncManager implements OnAccountsUpdatedListener { "unable to find " + operationToRemove + " in mOpsByWhen"); } - if (mSyncStorageEngine.deleteFromPending(operationToRemove.rowId) != 1) { + if (!mSyncStorageEngine.deleteFromPending(operationToRemove.pendingOperation)) { throw new IllegalStateException("unable to find pending row for " + operationToRemove); } @@ -2151,7 +2152,7 @@ class SyncManager implements OnAccountsUpdatedListener { throw new IllegalStateException("unable to find " + operation + " in mOpsByKey"); } - if (mSyncStorageEngine.deleteFromPending(operation.rowId) != 1) { + if (!mSyncStorageEngine.deleteFromPending(operation.pendingOperation)) { throw new IllegalStateException("unable to find pending row for " + operation); } @@ -2173,7 +2174,7 @@ class SyncManager implements OnAccountsUpdatedListener { "unable to find " + syncOperation + " in mOpsByWhen"); } - if (mSyncStorageEngine.deleteFromPending(syncOperation.rowId) != 1) { + if (!mSyncStorageEngine.deleteFromPending(syncOperation.pendingOperation)) { throw new IllegalStateException("unable to find pending row for " + syncOperation); } @@ -2214,49 +2215,29 @@ class SyncManager implements OnAccountsUpdatedListener { } if (checkDatabase) { - // check that the DB contains the same rows as the in-memory data structures - Cursor cursor = mSyncStorageEngine.getPendingSyncsCursor(COLUMNS); - try { - if (mOpsByKey.size() != cursor.getCount()) { - StringBuilder sb = new StringBuilder(); - DatabaseUtils.dumpCursor(cursor, sb); + final int N = mSyncStorageEngine.getPendingOperationCount(); + if (mOpsByKey.size() != N) { + ArrayList<SyncStorageEngine.PendingOperation> ops + = mSyncStorageEngine.getPendingOperations(); + StringBuilder sb = new StringBuilder(); + for (int i=0; i<N; i++) { + SyncStorageEngine.PendingOperation op = ops.get(i); + sb.append("#"); + sb.append(i); + sb.append(": account="); + sb.append(op.account); + sb.append(" syncSource="); + sb.append(op.syncSource); + sb.append(" authority="); + sb.append(op.authority); sb.append("\n"); - dump(sb); - throw new IllegalStateException("DB size mismatch: " - + mOpsByKey .size() + " != " + cursor.getCount() + "\n" - + sb.toString()); } - } finally { - cursor.close(); + dump(sb); + throw new IllegalStateException("DB size mismatch: " + + mOpsByKey.size() + " != " + N + "\n" + + sb.toString()); } } } - - private SyncOperation cursorToOperation(Cursor cursor) { - byte[] extrasData = cursor.getBlob(COLUMN_EXTRAS); - Bundle extras; - Parcel parcel = Parcel.obtain(); - try { - parcel.unmarshall(extrasData, 0, extrasData.length); - parcel.setDataPosition(0); - extras = parcel.readBundle(); - } catch (RuntimeException e) { - // A RuntimeException is thrown if we were unable to parse the parcel. - // Create an empty parcel in this case. - extras = new Bundle(); - } finally { - parcel.recycle(); - } - - SyncOperation syncOperation = new SyncOperation( - new Account(cursor.getString(COLUMN_ACCOUNT), - cursor.getString(COLUMN_ACCOUNT_TYPE)), - cursor.getInt(COLUMN_SOURCE), - cursor.getString(COLUMN_AUTHORITY), - extras, - 0 /* delay */); - syncOperation.rowId = cursor.getLong(COLUMN_ID); - return syncOperation; - } } } |