Limit who the SyncStatusObserver broadcasts are sent to.
Changes for ContentResolver.SYNC_OBSERVER_TYPE_* will only be
broadcasted to the user who registered the listener.
Bug: 128599864
Test: atest SyncStorageEngineTest
Test: atest com.android.service.content.SyncManagerTest
Test: atest CtsSyncManagerTest
Change-Id: Ib2482192644d2f2c4247b4d841a8598908bc4592
(cherry picked from commit 253c9f4d904ec3d232fc90692a4fb91e73eedb03)
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 6b441a0..c7a3f4b 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -43,6 +43,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Log;
@@ -54,6 +55,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IntPair;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -588,9 +590,10 @@
return mSyncRandomOffset;
}
- public void addStatusChangeListener(int mask, ISyncStatusObserver callback) {
+ public void addStatusChangeListener(int mask, int userId, ISyncStatusObserver callback) {
synchronized (mAuthorities) {
- mChangeListeners.register(callback, mask);
+ final long cookie = IntPair.of(userId, mask);
+ mChangeListeners.register(callback, cookie);
}
}
@@ -622,14 +625,16 @@
}
}
- void reportChange(int which) {
+ void reportChange(int which, int callingUserId) {
ArrayList<ISyncStatusObserver> reports = null;
synchronized (mAuthorities) {
int i = mChangeListeners.beginBroadcast();
while (i > 0) {
i--;
- Integer mask = (Integer)mChangeListeners.getBroadcastCookie(i);
- if ((which & mask.intValue()) == 0) {
+ final long cookie = (long) mChangeListeners.getBroadcastCookie(i);
+ final int userId = IntPair.first(cookie);
+ final int mask = IntPair.second(cookie);
+ if ((which & mask) == 0 || callingUserId != userId) {
continue;
}
if (reports == null) {
@@ -719,7 +724,7 @@
new Bundle(),
syncExemptionFlag, callingUid, callingPid);
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, userId);
queueBackup();
}
@@ -787,7 +792,7 @@
requestSync(aInfo, SyncOperation.REASON_IS_SYNCABLE, new Bundle(),
ContentResolver.SYNC_EXEMPTION_NONE, callingUid, callingPid);
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, target.userId);
}
public Pair<Long, Long> getBackoff(EndPoint info) {
@@ -833,7 +838,7 @@
}
}
if (changed) {
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, info.userId);
}
}
@@ -871,7 +876,7 @@
}
public void clearAllBackoffsLocked() {
- boolean changed = false;
+ final ArraySet<Integer> changedUserIds = new ArraySet<>();
synchronized (mAuthorities) {
// Clear backoff for all sync adapters.
for (AccountInfo accountInfo : mAccounts.values()) {
@@ -888,14 +893,14 @@
}
authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
- changed = true;
+ changedUserIds.add(accountInfo.accountAndUser.userId);
}
}
}
}
- if (changed) {
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ for (int i = changedUserIds.size() - 1; i > 0; i--) {
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, changedUserIds.valueAt(i));
}
}
@@ -921,7 +926,7 @@
}
authority.delayUntil = delayUntil;
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, info.userId);
}
/**
@@ -964,7 +969,7 @@
new Bundle(),
syncExemptionFlag, callingUid, callingPid);
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, userId);
mContext.sendBroadcast(ContentResolver.ACTION_SYNC_CONN_STATUS_CHANGED);
queueBackup();
}
@@ -1015,7 +1020,7 @@
SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
status.pending = pendingValue;
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING, info.userId);
}
/**
@@ -1103,7 +1108,7 @@
activeSyncContext.mStartTime);
getCurrentSyncs(authorityInfo.target.userId).add(syncInfo);
}
- reportActiveChange();
+ reportActiveChange(activeSyncContext.mSyncOperation.target.userId);
return syncInfo;
}
@@ -1120,14 +1125,14 @@
getCurrentSyncs(userId).remove(syncInfo);
}
- reportActiveChange();
+ reportActiveChange(userId);
}
/**
* To allow others to send active change reports, to poke clients.
*/
- public void reportActiveChange() {
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
+ public void reportActiveChange(int userId) {
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE, userId);
}
/**
@@ -1162,12 +1167,12 @@
if (Log.isLoggable(TAG, Log.VERBOSE)) Slog.v(TAG, "returning historyId " + id);
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS, op.target.userId);
return id;
}
public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
- long downstreamActivity, long upstreamActivity) {
+ long downstreamActivity, long upstreamActivity, int userId) {
synchronized (mAuthorities) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.v(TAG, "stopSyncEvent: historyId=" + historyId);
@@ -1307,7 +1312,7 @@
}
}
- reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS, userId);
}
/**