Skip to content

Commit a706e2f

Browse files
committed
Lock SyncQueue when user starting, copy RSC list.
Document SyncQueue locking policy and protect in onUserStarting() and clearAllBackoffs(). Return copy of ServiceInfo list from RegisteredServicesCache instead of exposing locking externally. Bug: 7357776, 7352537 Change-Id: I6a32ca98a355b639d4207a88bde572179beae359
1 parent 4682cf0 commit a706e2f

File tree

4 files changed

+38
-25
lines changed

4 files changed

+38
-25
lines changed

core/java/android/content/SyncManager.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import android.accounts.AccountManager;
2222
import android.accounts.AccountManagerService;
2323
import android.app.ActivityManager;
24-
import android.app.ActivityManagerNative;
2524
import android.app.AlarmManager;
2625
import android.app.Notification;
2726
import android.app.NotificationManager;
@@ -154,7 +153,9 @@ public class SyncManager {
154153
private AlarmManager mAlarmService = null;
155154

156155
private SyncStorageEngine mSyncStorageEngine;
157-
final public SyncQueue mSyncQueue;
156+
157+
// @GuardedBy("mSyncQueue")
158+
private final SyncQueue mSyncQueue;
158159

159160
protected final ArrayList<ActiveSyncContext> mActiveSyncContexts = Lists.newArrayList();
160161

@@ -902,7 +903,9 @@ private void onUserStarting(int userId) {
902903

903904
updateRunningAccounts();
904905

905-
mSyncQueue.addPendingOperations(userId);
906+
synchronized (mSyncQueue) {
907+
mSyncQueue.addPendingOperations(userId);
908+
}
906909

907910
// Schedule sync for any accounts under started user
908911
final Account[] accounts = AccountManagerService.getSingleton().getAccounts(userId);
@@ -1957,10 +1960,10 @@ private long maybeStartNextSyncLocked() {
19571960
synchronized (mSyncQueue) {
19581961
if (isLoggable) {
19591962
Log.v(TAG, "build the operation array, syncQueue size is "
1960-
+ mSyncQueue.mOperationsMap.size());
1963+
+ mSyncQueue.getOperations().size());
19611964
}
1962-
Iterator<SyncOperation> operationIterator =
1963-
mSyncQueue.mOperationsMap.values().iterator();
1965+
final Iterator<SyncOperation> operationIterator = mSyncQueue.getOperations()
1966+
.iterator();
19641967

19651968
final ActivityManager activityManager
19661969
= (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
@@ -2153,7 +2156,7 @@ private long maybeStartNextSyncLocked() {
21532156
runSyncFinishedOrCanceledLocked(null, toReschedule);
21542157
scheduleSyncOperation(toReschedule.mSyncOperation);
21552158
}
2156-
synchronized (mSyncQueue){
2159+
synchronized (mSyncQueue) {
21572160
mSyncQueue.remove(candidate);
21582161
}
21592162
dispatchSyncOperation(candidate);

core/java/android/content/SyncQueue.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@
2727
import com.google.android.collect.Maps;
2828

2929
import java.util.ArrayList;
30+
import java.util.Collection;
3031
import java.util.HashMap;
3132
import java.util.Iterator;
3233
import java.util.Map;
3334

3435
/**
36+
* Queue of pending sync operations. Not inherently thread safe, external
37+
* callers are responsible for locking.
3538
*
3639
* @hide
3740
*/
@@ -43,7 +46,7 @@ public class SyncQueue {
4346

4447
// A Map of SyncOperations operationKey -> SyncOperation that is designed for
4548
// quick lookup of an enqueued SyncOperation.
46-
public final HashMap<String, SyncOperation> mOperationsMap = Maps.newHashMap();
49+
private final HashMap<String, SyncOperation> mOperationsMap = Maps.newHashMap();
4750

4851
public SyncQueue(SyncStorageEngine syncStorageEngine, final SyncAdaptersCache syncAdapters) {
4952
mSyncStorageEngine = syncStorageEngine;
@@ -198,6 +201,10 @@ public void remove(Account account, int userId, String authority) {
198201
}
199202
}
200203

204+
public Collection<SyncOperation> getOperations() {
205+
return mOperationsMap.values();
206+
}
207+
201208
public void dump(StringBuilder sb) {
202209
final long now = SystemClock.elapsedRealtime();
203210
sb.append("SyncQueue: ").append(mOperationsMap.size()).append(" operation(s)\n");

core/java/android/content/SyncStorageEngine.java

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -609,23 +609,25 @@ public void setBackoff(Account account, int userId, String providerName,
609609
public void clearAllBackoffs(SyncQueue syncQueue) {
610610
boolean changed = false;
611611
synchronized (mAuthorities) {
612-
for (AccountInfo accountInfo : mAccounts.values()) {
613-
for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
614-
if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
615-
|| authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
616-
if (Log.isLoggable(TAG, Log.VERBOSE)) {
617-
Log.v(TAG, "clearAllBackoffs:"
618-
+ " authority:" + authorityInfo.authority
619-
+ " account:" + accountInfo.accountAndUser.account.name
620-
+ " user:" + accountInfo.accountAndUser.userId
621-
+ " backoffTime was: " + authorityInfo.backoffTime
622-
+ " backoffDelay was: " + authorityInfo.backoffDelay);
612+
synchronized (syncQueue) {
613+
for (AccountInfo accountInfo : mAccounts.values()) {
614+
for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
615+
if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
616+
|| authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
617+
if (Log.isLoggable(TAG, Log.VERBOSE)) {
618+
Log.v(TAG, "clearAllBackoffs:"
619+
+ " authority:" + authorityInfo.authority
620+
+ " account:" + accountInfo.accountAndUser.account.name
621+
+ " user:" + accountInfo.accountAndUser.userId
622+
+ " backoffTime was: " + authorityInfo.backoffTime
623+
+ " backoffDelay was: " + authorityInfo.backoffDelay);
624+
}
625+
authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
626+
authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
627+
syncQueue.onBackoffChanged(accountInfo.accountAndUser.account,
628+
accountInfo.accountAndUser.userId, authorityInfo.authority, 0);
629+
changed = true;
623630
}
624-
authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
625-
authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
626-
syncQueue.onBackoffChanged(accountInfo.accountAndUser.account,
627-
accountInfo.accountAndUser.userId, authorityInfo.authority, 0);
628-
changed = true;
629631
}
630632
}
631633
}

core/java/android/content/pm/RegisteredServicesCache.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ public Collection<ServiceInfo<V>> getAllServices(int userId) {
264264
if (user.services == null) {
265265
generateServicesMap(userId);
266266
}
267-
return Collections.unmodifiableCollection(user.services.values());
267+
return Collections.unmodifiableCollection(
268+
new ArrayList<ServiceInfo<V>>(user.services.values()));
268269
}
269270
}
270271

0 commit comments

Comments
 (0)