Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6669a7b4 authored by Fred Quintana's avatar Fred Quintana Committed by Android Git Automerger
Browse files

am 4a2f285d: am 77c560f3: - changed periodic sync scheduling to just creating...

am 4a2f285d: am 77c560f3: - changed periodic sync scheduling to just creating pending   and changed the "get next operation to sync" logic just look   at pending syncs, rather than them and periodic syncs - made syncoperation dup-detection ignore the initialization   

Merge commit '4a2f285d' into kraken

* commit '4a2f285d':
  - changed periodic sync scheduling to just creating pending
parents cba418b8 4a2f285d
Loading
Loading
Loading
Loading
+144 −123
Original line number Original line Diff line number Diff line
@@ -398,10 +398,6 @@ public class SyncManager implements OnAccountsUpdateListener {
        return minValue + random.nextInt((int)spread);
        return minValue + random.nextInt((int)spread);
    }
    }


    public ActiveSyncContext getActiveSyncContext() {
        return mActiveSyncContext;
    }

    public SyncStorageEngine getSyncStorageEngine() {
    public SyncStorageEngine getSyncStorageEngine() {
        return mSyncStorageEngine;
        return mSyncStorageEngine;
    }
    }
@@ -412,11 +408,6 @@ public class SyncManager implements OnAccountsUpdateListener {
        }
        }
    }
    }


    public Account getSyncingAccount() {
        ActiveSyncContext activeSyncContext = mActiveSyncContext;
        return (activeSyncContext != null) ? activeSyncContext.mSyncOperation.account : null;
    }

    private void initializeSyncAdapter(Account account, String authority) {
    private void initializeSyncAdapter(Account account, String authority) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "initializeSyncAdapter: " + account + ", authority " + authority);
            Log.v(TAG, "initializeSyncAdapter: " + account + ", authority " + authority);
@@ -425,7 +416,8 @@ public class SyncManager implements OnAccountsUpdateListener {
        RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
        RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
                mSyncAdapters.getServiceInfo(syncAdapterType);
                mSyncAdapters.getServiceInfo(syncAdapterType);
        if (syncAdapterInfo == null) {
        if (syncAdapterInfo == null) {
            Log.w(TAG, "can't find a sync adapter for " + syncAdapterType);
            Log.w(TAG, "can't find a sync adapter for " + syncAdapterType + ", removing");
            mSyncStorageEngine.removeAuthority(account, authority);
            return;
            return;
        }
        }


@@ -466,6 +458,8 @@ public class SyncManager implements OnAccountsUpdateListener {
                }
                }
            } catch (RemoteException e) {
            } catch (RemoteException e) {
                // doesn't matter, we will retry again later
                // doesn't matter, we will retry again later
                Log.d(TAG, "error while initializing: " + mAccount + ", authority " + mAuthority,
                        e);
            } finally {
            } finally {
                // give the sync adapter time to initialize before unbinding from it
                // give the sync adapter time to initialize before unbinding from it
                // TODO: change this API to not rely on this timing, http://b/2500805
                // TODO: change this API to not rely on this timing, http://b/2500805
@@ -602,16 +596,12 @@ public class SyncManager implements OnAccountsUpdateListener {
                        continue;
                        continue;
                    }
                    }


                    // initialize the SyncAdapter if the isSyncable state is unknown
                    // always allow if the isSyncable state is unknown
                    if (isSyncable < 0) {
                        initializeSyncAdapter(account, authority);
                        continue;
                    }

                    final boolean syncAutomatically = masterSyncAutomatically
                            && mSyncStorageEngine.getSyncAutomatically(account, authority);
                    boolean syncAllowed =
                    boolean syncAllowed =
                            ignoreSettings || (backgroundDataUsageAllowed && syncAutomatically);
                            (isSyncable < 0)
                            || ignoreSettings
                            || (backgroundDataUsageAllowed && masterSyncAutomatically
                                && mSyncStorageEngine.getSyncAutomatically(account, authority));
                    if (!syncAllowed) {
                    if (!syncAllowed) {
                        if (isLoggable) {
                        if (isLoggable) {
                            Log.d(TAG, "scheduleSync: sync of " + account + ", " + authority
                            Log.d(TAG, "scheduleSync: sync of " + account + ", " + authority
@@ -1061,7 +1051,7 @@ public class SyncManager implements OnAccountsUpdateListener {
                pw.println(op.expedited);
                pw.println(op.expedited);
                if (op.extras != null && op.extras.size() > 0) {
                if (op.extras != null && op.extras.size() > 0) {
                    sb.setLength(0);
                    sb.setLength(0);
                    SyncOperation.extrasToStringBuilder(op.extras, sb);
                    SyncOperation.extrasToStringBuilder(op.extras, sb, false /* asKey */);
                    pw.print("    extras: "); pw.println(sb.toString());
                    pw.print("    extras: "); pw.println(sb.toString());
                }
                }
            }
            }
@@ -1376,8 +1366,14 @@ public class SyncManager implements OnAccountsUpdateListener {
        }
        }


        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
            Long earliestFuturePollTime = null;
            try {
            try {
                waitUntilReadyToRun();
                waitUntilReadyToRun();
                // Always do this first so that we be sure that any periodic syncs that
                // are ready to run have been converted into pending syncs. This allows the
                // logic that considers the next steps to take based on the set of pending syncs
                // to also take into account the periodic syncs.
                earliestFuturePollTime = scheduleReadyPeriodicSyncs();
                switch (msg.what) {
                switch (msg.what) {
                    case SyncHandler.MESSAGE_SYNC_FINISHED:
                    case SyncHandler.MESSAGE_SYNC_FINISHED:
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -1486,48 +1482,90 @@ public class SyncManager implements OnAccountsUpdateListener {
                }
                }
                manageSyncNotification();
                manageSyncNotification();
                manageErrorNotification();
                manageErrorNotification();
                manageSyncAlarm();
                manageSyncAlarm(earliestFuturePollTime);
                mSyncTimeTracker.update();
                mSyncTimeTracker.update();
            }
            }
        }
        }


        private boolean isSyncAllowed(Account account, String authority, boolean ignoreSettings,
        /**
                boolean backgroundDataUsageAllowed) {
         * Turn any periodic sync operations that are ready to run into pending sync operations.
            Account[] accounts = mAccounts;
         * @return the desired start time of the earliest future  periodic sync operation,

         * in milliseconds since boot
         */
        private Long scheduleReadyPeriodicSyncs() {
            final boolean backgroundDataUsageAllowed =
                    getConnectivityManager().getBackgroundDataSetting();
            Long earliestFuturePollTime = null;
            if (!backgroundDataUsageAllowed || !mSyncStorageEngine.getMasterSyncAutomatically()) {
                return earliestFuturePollTime;
            }
            final long nowAbsolute = System.currentTimeMillis();
            ArrayList<SyncStorageEngine.AuthorityInfo> infos = mSyncStorageEngine.getAuthorities();
            for (SyncStorageEngine.AuthorityInfo info : infos) {
                // skip the sync if the account of this operation no longer exists
                // skip the sync if the account of this operation no longer exists
            if (!ArrayUtils.contains(accounts, account)) {
                if (!ArrayUtils.contains(mAccounts, info.account)) {
                return false;
                    continue;
                }
                }


            // skip the sync if it isn't manual and auto sync is disabled
                if (!mSyncStorageEngine.getSyncAutomatically(info.account, info.authority)) {
            final boolean syncAutomatically =
                    continue;
                    mSyncStorageEngine.getSyncAutomatically(account, authority)
                            && mSyncStorageEngine.getMasterSyncAutomatically();
            if (!(ignoreSettings || (backgroundDataUsageAllowed && syncAutomatically))) {
                return false;
                }
                }


            if (mSyncStorageEngine.getIsSyncable(account, authority) <= 0) {
                if (mSyncStorageEngine.getIsSyncable(info.account, info.authority) == 0) {
                // if not syncable or if the syncable is unknown (< 0), don't allow
                    continue;
                return false;
                }
                }


            return true;
                SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(info);
                for (int i = 0, N = info.periodicSyncs.size(); i < N; i++) {
                    final Bundle extras = info.periodicSyncs.get(i).first;
                    final Long periodInSeconds = info.periodicSyncs.get(i).second;
                    // find when this periodic sync was last scheduled to run
                    final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i);
                    // compute when this periodic sync should next run
                    long nextPollTimeAbsolute = lastPollTimeAbsolute + periodInSeconds * 1000;
                    // if it is ready to run then schedule it and mark it as having been scheduled
                    if (nextPollTimeAbsolute <= nowAbsolute) {
                        scheduleSyncOperation(
                                new SyncOperation(info.account, SyncStorageEngine.SOURCE_PERIODIC,
                                        info.authority, extras, 0 /* delay */));
                        status.setPeriodicSyncTime(i, nowAbsolute);
                    } else {
                        // it isn't ready to run, remember this time if it is earlier than
                        // earliestFuturePollTime
                        if (earliestFuturePollTime == null
                                || nextPollTimeAbsolute < earliestFuturePollTime) {
                            earliestFuturePollTime = nextPollTimeAbsolute;
                        }
                    }
                }
            }

            if (earliestFuturePollTime == null) {
                return null;
            }

            // convert absolute time to elapsed time
            return SystemClock.elapsedRealtime()
                    + ((earliestFuturePollTime < nowAbsolute)
                      ? 0
                      : (earliestFuturePollTime - nowAbsolute));
        }
        }


        private void runStateSyncing() {
        private void runStateSyncing() {
            // if the sync timeout has been reached then cancel it
            // if the sync timeout has been reached then cancel it

            ActiveSyncContext activeSyncContext = mActiveSyncContext;
            ActiveSyncContext activeSyncContext = mActiveSyncContext;


            final long now = SystemClock.elapsedRealtime();
            final long now = SystemClock.elapsedRealtime();
            if (now > activeSyncContext.mTimeoutStartTime + MAX_TIME_PER_SYNC) {
            if (now > activeSyncContext.mTimeoutStartTime + MAX_TIME_PER_SYNC) {
                SyncOperation nextSyncOperation;
                Pair<SyncOperation, Long> nextOpAndRunTime;
                synchronized (mSyncQueue) {
                synchronized (mSyncQueue) {
                    nextSyncOperation = getNextReadyToRunSyncOperation(now);
                    nextOpAndRunTime = mSyncQueue.nextOperation();
                }
                }
                if (nextSyncOperation != null) {
                SyncOperation curOp = activeSyncContext.mSyncOperation;
                if (nextOpAndRunTime != null
                        && nextOpAndRunTime.second <= now
                        && !nextOpAndRunTime.first.account.equals(curOp.account)
                        && !nextOpAndRunTime.first.authority.equals(curOp.authority)) {
                    Log.d(TAG, "canceling and rescheduling sync because it ran too long: "
                    Log.d(TAG, "canceling and rescheduling sync because it ran too long: "
                            + activeSyncContext.mSyncOperation);
                            + activeSyncContext.mSyncOperation);
                    scheduleSyncOperation(new SyncOperation(activeSyncContext.mSyncOperation));
                    scheduleSyncOperation(new SyncOperation(activeSyncContext.mSyncOperation));
@@ -1574,27 +1612,48 @@ public class SyncManager implements OnAccountsUpdateListener {
            // found that is runnable (not disabled, etc). If that one is ready to run then
            // found that is runnable (not disabled, etc). If that one is ready to run then
            // start it, otherwise just get out.
            // start it, otherwise just get out.
            SyncOperation op;
            SyncOperation op;
            int syncableState;
            final boolean backgroundDataUsageAllowed =
            final boolean backgroundDataUsageAllowed =
                    getConnectivityManager().getBackgroundDataSetting();
                    getConnectivityManager().getBackgroundDataSetting();
            final boolean masterSyncAutomatically = mSyncStorageEngine.getMasterSyncAutomatically();

            synchronized (mSyncQueue) {
            synchronized (mSyncQueue) {
                final long now = SystemClock.elapsedRealtime();
                final long now = SystemClock.elapsedRealtime();
                while (true) {
                while (true) {
                    op = getNextReadyToRunSyncOperation(now);
                    Pair<SyncOperation, Long> nextOpAndRunTime = mSyncQueue.nextOperation();
                    if (op == null) {
                    if (nextOpAndRunTime == null || nextOpAndRunTime.second > now) {
                        if (isLoggable) {
                        if (isLoggable) {
                            Log.v(TAG, "runStateIdle: no more sync operations, returning");
                            Log.v(TAG, "runStateIdle: no more ready sync operations, returning");
                        }
                        }
                        return;
                        return;
                    }
                    }
                    op = nextOpAndRunTime.first;


                    // we are either going to run this sync or drop it so go ahead and remove it
                    // we are either going to run this sync or drop it so go ahead and
                    // from the queue now
                    // remove it from the queue now
                    mSyncQueue.remove(op);
                    mSyncQueue.remove(op);


                    final boolean ignoreSettings = op.extras
                    // drop the sync if the account of this operation no longer exists
                            .getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
                    if (!ArrayUtils.contains(mAccounts, op.account)) {
                    if (!isSyncAllowed(op.account, op.authority, ignoreSettings,
                        continue;
                            backgroundDataUsageAllowed)) {
                    }


                    // drop this sync request if it isn't syncable, intializing the sync adapter
                    // if the syncable state is set to "unknown"
                    syncableState = mSyncStorageEngine.getIsSyncable(op.account, op.authority);
                    if (syncableState == 0) {
                        continue;
                    }

                    // skip the sync if it isn't manual and auto sync or
                    // background data usage is disabled
                    if (!op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false)
                            && (syncableState > 0)
                            && (!masterSyncAutomatically
                                || !backgroundDataUsageAllowed
                                || !mSyncStorageEngine.getSyncAutomatically(
                                       op.account, op.authority))) {
                        continue;
                        continue;
                    }
                    }


@@ -1608,6 +1667,19 @@ public class SyncManager implements OnAccountsUpdateListener {
                }
                }
            }
            }


            // convert the op into an initialization sync if the syncable state is "unknown" and
            // op isn't already an initialization sync. If it is marked syncable then convert
            // this into a regular sync
            final boolean initializeIsSet =
                    op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
            if (syncableState < 0 && !initializeIsSet) {
                op.extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
                op = new SyncOperation(op);
            } else if (syncableState > 0 && initializeIsSet) {
                op.extras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
                op = new SyncOperation(op);
            }

            // connect to the sync adapter
            // connect to the sync adapter
            SyncAdapterType syncAdapterType = SyncAdapterType.newKey(op.authority, op.account.type);
            SyncAdapterType syncAdapterType = SyncAdapterType.newKey(op.authority, op.account.type);
            RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
            RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
@@ -1643,74 +1715,6 @@ public class SyncManager implements OnAccountsUpdateListener {
            // MESSAGE_SERVICE_CONNECTED or MESSAGE_SERVICE_DISCONNECTED message
            // MESSAGE_SERVICE_CONNECTED or MESSAGE_SERVICE_DISCONNECTED message
        }
        }


        private SyncOperation getNextPeriodicSyncOperation() {
            final boolean backgroundDataUsageAllowed =
                    getConnectivityManager().getBackgroundDataSetting();
            SyncStorageEngine.AuthorityInfo best = null;
            long bestPollTimeAbsolute = Long.MAX_VALUE;
            Bundle bestExtras = null;
            ArrayList<SyncStorageEngine.AuthorityInfo> infos = mSyncStorageEngine.getAuthorities();
            for (SyncStorageEngine.AuthorityInfo info : infos) {
                if (!isSyncAllowed(info.account, info.authority, false /* ignoreSettings */,
                        backgroundDataUsageAllowed)) {
                    continue;
                }
                SyncStatusInfo status = mSyncStorageEngine.getStatusByAccountAndAuthority(
                        info.account, info.authority);
                int i = 0;
                for (Pair<Bundle, Long> periodicSync : info.periodicSyncs) {
                    long lastPollTimeAbsolute = status != null ? status.getPeriodicSyncTime(i) : 0;
                    final Bundle extras = periodicSync.first;
                    final Long periodInSeconds = periodicSync.second;
                    long nextPollTimeAbsolute = lastPollTimeAbsolute + periodInSeconds * 1000;
                    if (nextPollTimeAbsolute < bestPollTimeAbsolute) {
                        best = info;
                        bestPollTimeAbsolute = nextPollTimeAbsolute;
                        bestExtras = extras;
                    }
                    i++;
                }
            }

            if (best == null) {
                return null;
            }

            final long nowAbsolute = System.currentTimeMillis();
            final SyncOperation syncOperation = new SyncOperation(best.account,
                    SyncStorageEngine.SOURCE_PERIODIC,
                    best.authority, bestExtras, 0 /* delay */);
            syncOperation.earliestRunTime = SystemClock.elapsedRealtime()
                    + (bestPollTimeAbsolute - nowAbsolute);
            if (syncOperation.earliestRunTime < 0) {
                syncOperation.earliestRunTime = 0;
            }
            return syncOperation;
        }

        public Pair<SyncOperation, Long> bestSyncOperationCandidate() {
            Pair<SyncOperation, Long> nextOpAndRunTime = mSyncQueue.nextOperation();
            SyncOperation nextOp = nextOpAndRunTime != null ? nextOpAndRunTime.first : null;
            Long nextRunTime = nextOpAndRunTime != null ? nextOpAndRunTime.second : null;
            SyncOperation pollOp = getNextPeriodicSyncOperation();
            if (nextOp != null
                    && (pollOp == null || nextOp.expedited
                        || nextRunTime <= pollOp.earliestRunTime)) {
                return nextOpAndRunTime;
            } else if (pollOp != null) {
                return Pair.create(pollOp, pollOp.earliestRunTime);
            } else {
                return null;
            }
        }

        private SyncOperation getNextReadyToRunSyncOperation(long now) {
            Pair<SyncOperation, Long> nextOpAndRunTime = bestSyncOperationCandidate();
            return nextOpAndRunTime != null && nextOpAndRunTime.second <= now
                    ? nextOpAndRunTime.first
                    : null;
        }

        private void runBoundToSyncAdapter(ISyncAdapter syncAdapter) {
        private void runBoundToSyncAdapter(ISyncAdapter syncAdapter) {
            mActiveSyncContext.mSyncAdapter = syncAdapter;
            mActiveSyncContext.mSyncAdapter = syncAdapter;
            final SyncOperation syncOperation = mActiveSyncContext.mSyncOperation;
            final SyncOperation syncOperation = mActiveSyncContext.mSyncOperation;
@@ -1757,6 +1761,15 @@ public class SyncManager implements OnAccountsUpdateListener {
                    downstreamActivity = 0;
                    downstreamActivity = 0;
                    upstreamActivity = 0;
                    upstreamActivity = 0;
                    clearBackoffSetting(syncOperation);
                    clearBackoffSetting(syncOperation);
                    // if this was an initialization sync and the sync adapter is now
                    // marked syncable then reschedule the sync. The next time it runs it
                    // will be made into a regular sync.
                    if (syncOperation.extras.getBoolean(
                                ContentResolver.SYNC_EXTRAS_INITIALIZE, false)
                            && mSyncStorageEngine.getIsSyncable(
                                syncOperation.account, syncOperation.authority) > 0) {
                        scheduleSyncOperation(new SyncOperation(syncOperation));
                    }
                } else {
                } else {
                    Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
                    Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
                    // the operation failed so increase the backoff time
                    // the operation failed so increase the backoff time
@@ -1919,7 +1932,7 @@ public class SyncManager implements OnAccountsUpdateListener {
            }
            }
        }
        }


        private void manageSyncAlarm() {
        private void manageSyncAlarm(Long earliestFuturePollElapsedTime) {
            // in each of these cases the sync loop will be kicked, which will cause this
            // in each of these cases the sync loop will be kicked, which will cause this
            // method to be called again
            // method to be called again
            if (!mDataConnectionIsConnected) return;
            if (!mDataConnectionIsConnected) return;
@@ -1935,8 +1948,16 @@ public class SyncManager implements OnAccountsUpdateListener {
            ActiveSyncContext activeSyncContext = mActiveSyncContext;
            ActiveSyncContext activeSyncContext = mActiveSyncContext;
            if (activeSyncContext == null) {
            if (activeSyncContext == null) {
                synchronized (mSyncQueue) {
                synchronized (mSyncQueue) {
                    Pair<SyncOperation, Long> candidate = bestSyncOperationCandidate();
                    final Pair<SyncOperation, Long> candidate = mSyncQueue.nextOperation();
                    alarmTime = candidate != null ? candidate.second : null;
                    if (earliestFuturePollElapsedTime == null && candidate == null) {
                        alarmTime = null;
                    } else if (earliestFuturePollElapsedTime == null) {
                        alarmTime = candidate.second;
                    } else if (candidate == null) {
                        alarmTime = earliestFuturePollElapsedTime;
                    } else {
                        alarmTime = Math.min(earliestFuturePollElapsedTime, candidate.second);
                    }
                }
                }
            } else {
            } else {
                final long notificationTime =
                final long notificationTime =
@@ -2077,7 +2098,7 @@ public class SyncManager implements OnAccountsUpdateListener {
                                SyncStorageEngine.EVENT_STOP, syncOperation.syncSource,
                                SyncStorageEngine.EVENT_STOP, syncOperation.syncSource,
                                syncOperation.account.name.hashCode());
                                syncOperation.account.name.hashCode());


            mSyncStorageEngine.stopSyncEvent(rowId, syncOperation.extras, elapsedTime,
            mSyncStorageEngine.stopSyncEvent(rowId, elapsedTime,
                    resultMessage, downstreamActivity, upstreamActivity);
                    resultMessage, downstreamActivity, upstreamActivity);
        }
        }
    }
    }
+9 −3
Original line number Original line Diff line number Diff line
@@ -80,7 +80,7 @@ public class SyncOperation implements Comparable {
        sb.append("authority: ").append(authority);
        sb.append("authority: ").append(authority);
        sb.append(" account: ").append(account);
        sb.append(" account: ").append(account);
        sb.append(" extras: ");
        sb.append(" extras: ");
        extrasToStringBuilder(extras, sb);
        extrasToStringBuilder(extras, sb, false /* asKey */);
        sb.append(" syncSource: ").append(syncSource);
        sb.append(" syncSource: ").append(syncSource);
        sb.append(" when: ").append(earliestRunTime);
        sb.append(" when: ").append(earliestRunTime);
        sb.append(" expedited: ").append(expedited);
        sb.append(" expedited: ").append(expedited);
@@ -92,13 +92,19 @@ public class SyncOperation implements Comparable {
        sb.append("authority: ").append(authority);
        sb.append("authority: ").append(authority);
        sb.append(" account: ").append(account);
        sb.append(" account: ").append(account);
        sb.append(" extras: ");
        sb.append(" extras: ");
        extrasToStringBuilder(extras, sb);
        extrasToStringBuilder(extras, sb, true /* asKey */);
        return sb.toString();
        return sb.toString();
    }
    }


    public static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
    public static void extrasToStringBuilder(Bundle bundle, StringBuilder sb, boolean asKey) {
        sb.append("[");
        sb.append("[");
        for (String key : bundle.keySet()) {
        for (String key : bundle.keySet()) {
            // if we are writing this as a key don't consider whether this
            // is an initialization sync or not when computing the key since
            // we set this flag appropriately when dispatching the sync request.
            if (asKey && ContentResolver.SYNC_EXTRAS_INITIALIZE.equals(key)) {
                continue;
            }
            sb.append(key).append("=").append(bundle.get(key)).append(" ");
            sb.append(key).append("=").append(bundle.get(key)).append(" ");
        }
        }
        sb.append("]");
        sb.append("]");
+20 −6
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package android.content;
package android.content;


import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Maps;


import android.util.Pair;
import android.util.Pair;
@@ -120,14 +121,16 @@ public class SyncQueue {


    /**
    /**
     * Find the operation that should run next. Operations are sorted by their earliestRunTime,
     * Find the operation that should run next. Operations are sorted by their earliestRunTime,
     * prioritizing expedited operations. The earliestRunTime is adjusted by the sync adapter's
     * prioritizing first those with a syncable state of "unknown" that aren't retries then
     * backoff and delayUntil times, if any.
     * expedited operations.
     * The earliestRunTime is adjusted by the sync adapter's backoff and delayUntil times, if any.
     * @return the operation that should run next and when it should run. The time may be in
     * @return the operation that should run next and when it should run. The time may be in
     * the future. It is expressed in milliseconds since boot.
     * the future. It is expressed in milliseconds since boot.
     */
     */
    public Pair<SyncOperation, Long> nextOperation() {
    public Pair<SyncOperation, Long> nextOperation() {
        SyncOperation best = null;
        SyncOperation best = null;
        long bestRunTime = 0;
        long bestRunTime = 0;
        boolean bestSyncableIsUnknownAndNotARetry = false;
        for (SyncOperation op : mOperationsMap.values()) {
        for (SyncOperation op : mOperationsMap.values()) {
            long opRunTime = op.earliestRunTime;
            long opRunTime = op.earliestRunTime;
            if (!op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false)) {
            if (!op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false)) {
@@ -137,12 +140,23 @@ public class SyncQueue {
                        Math.max(opRunTime, delayUntil),
                        Math.max(opRunTime, delayUntil),
                        backoff != null ? backoff.first : 0);
                        backoff != null ? backoff.first : 0);
            }
            }
            // if the expedited state of both ops are the same then compare their runtime.
            // we know a sync is a retry if the intialization flag is set, since that will only
            // Otherwise the candidate is only better than the current best if the candidate
            // be set by the sync dispatching code, thus if it is set it must have already been
            // is expedited.
            // dispatched
            final boolean syncableIsUnknownAndNotARetry =
                    !op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)
                    && mSyncStorageEngine.getIsSyncable(op.account, op.authority) < 0;
            // if the unsyncable state differs, make the current the best if it is unsyncable
            // else, if the expedited state differs, make the current the best if it is expedited
            // else, make the current the best if it is earlier than the best
            if (best == null
            if (best == null
                    || (best.expedited == op.expedited ? opRunTime < bestRunTime : op.expedited)) {
                    || ((bestSyncableIsUnknownAndNotARetry == syncableIsUnknownAndNotARetry)
                        ? (best.expedited == op.expedited
                           ? opRunTime < bestRunTime
                           : op.expedited)
                        : syncableIsUnknownAndNotARetry)) {
                best = op;
                best = op;
                bestSyncableIsUnknownAndNotARetry = syncableIsUnknownAndNotARetry;
                bestRunTime = opRunTime;
                bestRunTime = opRunTime;
            }
            }
        }
        }
+134 −100

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Original line Diff line number Diff line
@@ -51,7 +51,7 @@ public class SyncStorageEngineTest extends AndroidTestCase {
        long historyId = engine.insertStartSyncEvent(
        long historyId = engine.insertStartSyncEvent(
                account, authority, time0, SyncStorageEngine.SOURCE_LOCAL);
                account, authority, time0, SyncStorageEngine.SOURCE_LOCAL);
        long time1 = time0 + SyncStorageEngine.MILLIS_IN_4WEEKS * 2;
        long time1 = time0 + SyncStorageEngine.MILLIS_IN_4WEEKS * 2;
        engine.stopSyncEvent(historyId, new Bundle(), time1 - time0, "yay", 0, 0);
        engine.stopSyncEvent(historyId, time1 - time0, "yay", 0, 0);
    }
    }


    /**
    /**