115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root/* 215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Copyright (C) 2010 The Android Open Source Project 315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * you may not use this file except in compliance with the License. 615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * You may obtain a copy of the License at 715a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 815a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * http://www.apache.org/licenses/LICENSE-2.0 915a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 1015a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Unless required by applicable law or agreed to in writing, software 1115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 1215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * See the License for the specific language governing permissions and 1415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * limitations under the License. 1515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root */ 1615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root 177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.android.server.content; 18307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 1957286f970641493b315b0b42aba7ac6b672cc8b8Alon Albertimport android.content.pm.PackageManager; 207a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.SyncAdapterType; 217a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.content.SyncAdaptersCache; 226ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport android.content.pm.RegisteredServicesCache.ServiceInfo; 2356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williamsimport android.os.Bundle; 24918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintanaimport android.os.SystemClock; 25918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintanaimport android.text.format.DateUtils; 26307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanaimport android.util.Log; 276ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport android.util.Pair; 286ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey 296ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport com.google.android.collect.Maps; 30307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 31307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanaimport java.util.ArrayList; 32a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkeyimport java.util.Collection; 33918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintanaimport java.util.HashMap; 34307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanaimport java.util.Iterator; 35918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintanaimport java.util.Map; 36307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 37307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana/** 38a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey * Queue of pending sync operations. Not inherently thread safe, external 39a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey * callers are responsible for locking. 40307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana * 41307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana * @hide 42307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana */ 43307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintanapublic class SyncQueue { 44307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana private static final String TAG = "SyncManager"; 456ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey private final SyncStorageEngine mSyncStorageEngine; 466ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey private final SyncAdaptersCache mSyncAdapters; 4757286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert private final PackageManager mPackageManager; 48307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 49307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana // A Map of SyncOperations operationKey -> SyncOperation that is designed for 50307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana // quick lookup of an enqueued SyncOperation. 51a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey private final HashMap<String, SyncOperation> mOperationsMap = Maps.newHashMap(); 52307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 5357286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert public SyncQueue(PackageManager packageManager, SyncStorageEngine syncStorageEngine, 5457286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert final SyncAdaptersCache syncAdapters) { 5557286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert mPackageManager = packageManager; 56307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana mSyncStorageEngine = syncStorageEngine; 576ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey mSyncAdapters = syncAdapters; 586ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey } 596ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey 606ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey public void addPendingOperations(int userId) { 616ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey for (SyncStorageEngine.PendingOperation op : mSyncStorageEngine.getPendingOperations()) { 628ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams final SyncStorageEngine.EndPoint info = op.target; 6356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams if (info.userId != userId) continue; 6456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams 6556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(info); 6656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams SyncOperation operationToAdd; 6756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams if (info.target_provider) { 6856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams final ServiceInfo<SyncAdapterType> syncAdapterInfo = mSyncAdapters.getServiceInfo( 6956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams SyncAdapterType.newKey(info.provider, info.account.type), info.userId); 7056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams if (syncAdapterInfo == null) { 7156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams if (Log.isLoggable(TAG, Log.VERBOSE)) { 728ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams Log.v(TAG, "Missing sync adapter info for authority " + op.target); 7356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } 7456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams continue; 7556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } 7656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams operationToAdd = new SyncOperation( 7756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams info.account, info.userId, op.reason, op.syncSource, info.provider, 7856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams op.extras, 796428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams op.expedited ? -1 : 0 /* delay */, 8056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams 0 /* flex */, 816428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams backoff != null ? backoff.first : 0L, 8256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams mSyncStorageEngine.getDelayUntilTime(info), 8356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams syncAdapterInfo.type.allowParallelSyncs()); 8456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams operationToAdd.pendingOperation = op; 8556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams add(operationToAdd, op); 8656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } else if (info.target_service) { 8756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams try { 8856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams mPackageManager.getServiceInfo(info.service, 0); 8956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } catch (PackageManager.NameNotFoundException e) { 9056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams if (Log.isLoggable(TAG, Log.VERBOSE)) { 918ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams Log.w(TAG, "Missing sync service for authority " + op.target); 9256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } 9356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams continue; 9456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } 9556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams operationToAdd = new SyncOperation( 9656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams info.service, info.userId, op.reason, op.syncSource, 9756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams op.extras, 986428046767ee4195617fb41b5639eefa2ca7a939Matthew Williams op.expedited ? -1 : 0 /* delay */, 9956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams 0 /* flex */, 10056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams backoff != null ? backoff.first : 0, 10156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams mSyncStorageEngine.getDelayUntilTime(info)); 10256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams operationToAdd.pendingOperation = op; 10356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams add(operationToAdd, op); 1040c4d04ac2e8aa62560d8d767fa1c87e5361b0b08Fred Quintana } 105307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 106307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 107307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 108307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana public boolean add(SyncOperation operation) { 109307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana return add(operation, null /* this is not coming from the database */); 110307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 111307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 112fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams /** 113fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * Adds a SyncOperation to the queue and creates a PendingOperation object to track that sync. 114fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * If an operation is added that already exists, the existing operation is updated if the newly 115fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams * added operation occurs before (or the interval overlaps). 116fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams */ 117307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana private boolean add(SyncOperation operation, 118307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana SyncStorageEngine.PendingOperation pop) { 119fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // If an operation with the same key exists and this one should run sooner/overlaps, 120fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // replace the run interval of the existing operation with this new one. 121fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // Complications: what if the existing operation is expedited but the new operation has an 122fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // earlier run time? Will not be a problem for periodic syncs (no expedited flag), and for 123fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // one-off syncs we only change it if the new sync is sooner. 124307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana final String operationKey = operation.key; 125307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana final SyncOperation existingOperation = mOperationsMap.get(operationKey); 126307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 127307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana if (existingOperation != null) { 128307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana boolean changed = false; 129fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams if (operation.compareTo(existingOperation) <= 0 ) { 130fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams long newRunTime = 131fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams Math.min(existingOperation.latestRunTime, operation.latestRunTime); 132fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // Take smaller runtime. 133fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams existingOperation.latestRunTime = newRunTime; 134fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // Take newer flextime. 135fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams existingOperation.flexTime = operation.flexTime; 136fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams changed = true; 137307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 138307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana return changed; 139307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 140307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 141307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana operation.pendingOperation = pop; 142fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // Don't update the PendingOp if one already exists. This really is just a placeholder, 143fa77418134c6f1f80af225a78819f069e9c974fbMatthew Williams // no actual scheduling info is placed here. 144307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana if (operation.pendingOperation == null) { 14556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams pop = mSyncStorageEngine.insertIntoPending(operation); 146307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana if (pop == null) { 147307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana throw new IllegalStateException("error adding pending sync operation " 148307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana + operation); 149307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 150307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana operation.pendingOperation = pop; 151307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 152307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 153307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana mOperationsMap.put(operationKey, operation); 154307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana return true; 155307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 156307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 15756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams public void removeUserLocked(int userId) { 158135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani ArrayList<SyncOperation> opsToRemove = new ArrayList<SyncOperation>(); 159135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani for (SyncOperation op : mOperationsMap.values()) { 16056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams if (op.target.userId == userId) { 161135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani opsToRemove.add(op); 162135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani } 163135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani } 16456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams for (SyncOperation op : opsToRemove) { 16556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams remove(op); 16656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } 167135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani } 168135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani 169c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana /** 170c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * Remove the specified operation if it is in the queue. 171c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana * @param operation the operation to remove 172c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana */ 173307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana public void remove(SyncOperation operation) { 1748ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE); 175307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana SyncOperation operationToRemove = mOperationsMap.remove(operation.key); 17656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams if (isLoggable) { 1778ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams Log.v(TAG, "Attempting to remove: " + operation.key); 17856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } 179c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana if (operationToRemove == null) { 18056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams if (isLoggable) { 1818ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams Log.v(TAG, "Could not find: " + operation.key); 18256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } 183c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana return; 184c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 185307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana if (!mSyncStorageEngine.deleteFromPending(operationToRemove.pendingOperation)) { 186307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana final String errorMessage = "unable to find pending row for " + operationToRemove; 187307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana Log.e(TAG, errorMessage, new IllegalStateException(errorMessage)); 188307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 189307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 190307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 19156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams /** Reset backoffs for all operations in the queue. */ 19256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams public void clearBackoffs() { 19356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams for (SyncOperation op : mOperationsMap.values()) { 19456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams op.backoff = 0L; 19556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams op.updateEffectiveRunTime(); 19656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } 19756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams } 19856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams 19956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams public void onBackoffChanged(SyncStorageEngine.EndPoint target, long backoff) { 2008ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams // For each op that matches the target of the changed op, update its 201918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana // backoff and effectiveStartTime 202307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana for (SyncOperation op : mOperationsMap.values()) { 2038ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams if (op.target.matchesSpec(target)) { 204918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana op.backoff = backoff; 205918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana op.updateEffectiveRunTime(); 206307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 207307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 208307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 209307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 21056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams public void onDelayUntilTimeChanged(SyncStorageEngine.EndPoint target, long delayUntil) { 2118ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams // for each op that matches the target info of the provided op, change the delay time. 212918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana for (SyncOperation op : mOperationsMap.values()) { 2138ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams if (op.target.matchesSpec(target)) { 214918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana op.delayUntil = delayUntil; 215918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana op.updateEffectiveRunTime(); 216918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana } 217307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 218307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 219307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 22056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams /** 22156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams * Remove all of the SyncOperations associated with a given target. 22256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams * 22356dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams * @param info target object provided here can have null Account/provider. This is the case 22456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams * where you want to remove all ops associated with a provider (null Account) or all ops 22556dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams * associated with an account (null provider). 22656dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams * @param extras option bundle to include to further specify which operation to remove. If this 22756dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams * bundle contains sync settings flags, they are ignored. 22856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams */ 22956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams public void remove(final SyncStorageEngine.EndPoint info, Bundle extras) { 230307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana Iterator<Map.Entry<String, SyncOperation>> entries = mOperationsMap.entrySet().iterator(); 231307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana while (entries.hasNext()) { 232307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana Map.Entry<String, SyncOperation> entry = entries.next(); 233307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana SyncOperation syncOperation = entry.getValue(); 23456dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams final SyncStorageEngine.EndPoint opInfo = syncOperation.target; 2358ef2204c8f5f9744a2ff7abdbbf2d26a5ea02837Matthew Williams if (!opInfo.matchesSpec(info)) { 236c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana continue; 237c5d1c6db61f208b206b260f897bb5bbc64be4d97Fred Quintana } 23856dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams if (extras != null 23956dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams && !SyncManager.syncExtrasEquals( 24056dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams syncOperation.extras, 24156dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams extras, 24256dbf8f23677d28615e61ef2fbb0e738cca02528Matthew Williams false /* no config flags*/)) { 24304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani continue; 24404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani } 245307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana entries.remove(); 246307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana if (!mSyncStorageEngine.deleteFromPending(syncOperation.pendingOperation)) { 247307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana final String errorMessage = "unable to find pending row for " + syncOperation; 248307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana Log.e(TAG, errorMessage, new IllegalStateException(errorMessage)); 249307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 250307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 251307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 252307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 253a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey public Collection<SyncOperation> getOperations() { 254a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey return mOperationsMap.values(); 255a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey } 256a706e2fd0059b1bb86c487722dbc9fc0fda9c980Jeff Sharkey 257307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana public void dump(StringBuilder sb) { 258918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana final long now = SystemClock.elapsedRealtime(); 259307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana sb.append("SyncQueue: ").append(mOperationsMap.size()).append(" operation(s)\n"); 260307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana for (SyncOperation operation : mOperationsMap.values()) { 261918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana sb.append(" "); 262918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana if (operation.effectiveRunTime <= now) { 263918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana sb.append("READY"); 264918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana } else { 265918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana sb.append(DateUtils.formatElapsedTime((operation.effectiveRunTime - now) / 1000)); 266918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana } 267918339ab8255f8e1d03d8448ab1d9036c7c15173Fred Quintana sb.append(" - "); 26857286f970641493b315b0b42aba7ac6b672cc8b8Alon Albert sb.append(operation.dump(mPackageManager, false)).append("\n"); 269307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 270307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 271307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana} 272