Merge "Handle Concurrency issues in Connection" into nyc-dev
This commit is contained in:
@@ -82,6 +82,7 @@ public abstract class Conference extends Conferenceable {
|
|||||||
private StatusHints mStatusHints;
|
private StatusHints mStatusHints;
|
||||||
private Bundle mExtras;
|
private Bundle mExtras;
|
||||||
private Set<String> mPreviousExtraKeys;
|
private Set<String> mPreviousExtraKeys;
|
||||||
|
private final Object mExtrasLock = new Object();
|
||||||
|
|
||||||
private final Connection.Listener mConnectionDeathListener = new Connection.Listener() {
|
private final Connection.Listener mConnectionDeathListener = new Connection.Listener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -686,32 +687,35 @@ public abstract class Conference extends Conferenceable {
|
|||||||
* @param extras The extras associated with this {@code Conference}.
|
* @param extras The extras associated with this {@code Conference}.
|
||||||
*/
|
*/
|
||||||
public final void setExtras(@Nullable Bundle extras) {
|
public final void setExtras(@Nullable Bundle extras) {
|
||||||
// Add/replace any new or changed extras values.
|
// Keeping putExtras and removeExtras in the same lock so that this operation happens as a
|
||||||
putExtras(extras);
|
// block instead of letting other threads put/remove while this method is running.
|
||||||
|
synchronized (mExtrasLock) {
|
||||||
|
// Add/replace any new or changed extras values.
|
||||||
|
putExtras(extras);
|
||||||
|
// If we have used "setExtras" in the past, compare the key set from the last invocation
|
||||||
|
// to the current one and remove any keys that went away.
|
||||||
|
if (mPreviousExtraKeys != null) {
|
||||||
|
List<String> toRemove = new ArrayList<String>();
|
||||||
|
for (String oldKey : mPreviousExtraKeys) {
|
||||||
|
if (extras == null || !extras.containsKey(oldKey)) {
|
||||||
|
toRemove.add(oldKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If we have used "setExtras" in the past, compare the key set from the last invocation to
|
if (!toRemove.isEmpty()) {
|
||||||
// the current one and remove any keys that went away.
|
removeExtras(toRemove);
|
||||||
if (mPreviousExtraKeys != null) {
|
|
||||||
List<String> toRemove = new ArrayList<String>();
|
|
||||||
for (String oldKey : mPreviousExtraKeys) {
|
|
||||||
if (extras == null || !extras.containsKey(oldKey)) {
|
|
||||||
toRemove.add(oldKey);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!toRemove.isEmpty()) {
|
// Track the keys the last time set called setExtras. This way, the next time setExtras
|
||||||
removeExtras(toRemove);
|
// is called we can see if the caller has removed any extras values.
|
||||||
|
if (mPreviousExtraKeys == null) {
|
||||||
|
mPreviousExtraKeys = new ArraySet<String>();
|
||||||
|
}
|
||||||
|
mPreviousExtraKeys.clear();
|
||||||
|
if (extras != null) {
|
||||||
|
mPreviousExtraKeys.addAll(extras.keySet());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Track the keys the last time set called setExtras. This way, the next time setExtras is
|
|
||||||
// called we can see if the caller has removed any extras values.
|
|
||||||
if (mPreviousExtraKeys == null) {
|
|
||||||
mPreviousExtraKeys = new ArraySet<String>();
|
|
||||||
}
|
|
||||||
mPreviousExtraKeys.clear();
|
|
||||||
if (extras != null) {
|
|
||||||
mPreviousExtraKeys.addAll(extras.keySet());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,13 +734,19 @@ public abstract class Conference extends Conferenceable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExtras == null) {
|
// Creating a Bundle clone so we don't have to synchronize on mExtrasLock while calling
|
||||||
mExtras = new Bundle();
|
// onExtrasChanged.
|
||||||
|
Bundle listenersBundle;
|
||||||
|
synchronized (mExtrasLock) {
|
||||||
|
if (mExtras == null) {
|
||||||
|
mExtras = new Bundle();
|
||||||
|
}
|
||||||
|
mExtras.putAll(extras);
|
||||||
|
listenersBundle = new Bundle(mExtras);
|
||||||
}
|
}
|
||||||
mExtras.putAll(extras);
|
|
||||||
|
|
||||||
for (Listener l : mListeners) {
|
for (Listener l : mListeners) {
|
||||||
l.onExtrasChanged(this, extras);
|
l.onExtrasChanged(this, new Bundle(listenersBundle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,17 +800,17 @@ public abstract class Conference extends Conferenceable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mExtras != null) {
|
synchronized (mExtrasLock) {
|
||||||
for (String key : keys) {
|
if (mExtras != null) {
|
||||||
mExtras.remove(key);
|
for (String key : keys) {
|
||||||
}
|
mExtras.remove(key);
|
||||||
if (mExtras.size() == 0) {
|
}
|
||||||
mExtras = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> unmodifiableKeys = Collections.unmodifiableList(keys);
|
||||||
for (Listener l : mListeners) {
|
for (Listener l : mListeners) {
|
||||||
l.onExtrasRemoved(this, keys);
|
l.onExtrasRemoved(this, unmodifiableKeys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -833,7 +843,13 @@ public abstract class Conference extends Conferenceable {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
final void handleExtrasChanged(Bundle extras) {
|
final void handleExtrasChanged(Bundle extras) {
|
||||||
mExtras = extras;
|
Bundle b = null;
|
||||||
onExtrasChanged(mExtras);
|
synchronized (mExtrasLock) {
|
||||||
|
mExtras = extras;
|
||||||
|
if (mExtras != null) {
|
||||||
|
b = new Bundle(mExtras);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onExtrasChanged(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1239,6 +1239,7 @@ public abstract class Connection extends Conferenceable {
|
|||||||
private Conference mConference;
|
private Conference mConference;
|
||||||
private ConnectionService mConnectionService;
|
private ConnectionService mConnectionService;
|
||||||
private Bundle mExtras;
|
private Bundle mExtras;
|
||||||
|
private final Object mExtrasLock = new Object();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks the key set for the extras bundle provided on the last invocation of
|
* Tracks the key set for the extras bundle provided on the last invocation of
|
||||||
@@ -1388,7 +1389,13 @@ public abstract class Connection extends Conferenceable {
|
|||||||
* @return The extras associated with this connection.
|
* @return The extras associated with this connection.
|
||||||
*/
|
*/
|
||||||
public final Bundle getExtras() {
|
public final Bundle getExtras() {
|
||||||
return mExtras;
|
Bundle extras = null;
|
||||||
|
synchronized (mExtrasLock) {
|
||||||
|
if (mExtras != null) {
|
||||||
|
extras = new Bundle(mExtras);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return extras;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1924,14 +1931,20 @@ public abstract class Connection extends Conferenceable {
|
|||||||
if (extras == null) {
|
if (extras == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Creating a duplicate bundle so we don't have to synchronize on mExtrasLock while calling
|
||||||
if (mExtras == null) {
|
// the listeners.
|
||||||
mExtras = new Bundle();
|
Bundle listenerExtras;
|
||||||
|
synchronized (mExtrasLock) {
|
||||||
|
if (mExtras == null) {
|
||||||
|
mExtras = new Bundle();
|
||||||
|
}
|
||||||
|
mExtras.putAll(extras);
|
||||||
|
listenerExtras = new Bundle(mExtras);
|
||||||
}
|
}
|
||||||
mExtras.putAll(extras);
|
|
||||||
|
|
||||||
for (Listener l : mListeners) {
|
for (Listener l : mListeners) {
|
||||||
l.onExtrasChanged(this, extras);
|
// Create a new clone of the extras for each listener so that they don't clobber
|
||||||
|
// each other
|
||||||
|
l.onExtrasChanged(this, new Bundle(listenerExtras));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1981,18 +1994,16 @@ public abstract class Connection extends Conferenceable {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public final void removeExtras(List<String> keys) {
|
public final void removeExtras(List<String> keys) {
|
||||||
if (mExtras != null) {
|
synchronized (mExtrasLock) {
|
||||||
for (String key : keys) {
|
if (mExtras != null) {
|
||||||
mExtras.remove(key);
|
for (String key : keys) {
|
||||||
}
|
mExtras.remove(key);
|
||||||
|
}
|
||||||
if (mExtras.size() == 0) {
|
|
||||||
mExtras = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
List<String> unmodifiableKeys = Collections.unmodifiableList(keys);
|
||||||
for (Listener l : mListeners) {
|
for (Listener l : mListeners) {
|
||||||
l.onExtrasRemoved(this, keys);
|
l.onExtrasRemoved(this, unmodifiableKeys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2274,8 +2285,14 @@ public abstract class Connection extends Conferenceable {
|
|||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
final void handleExtrasChanged(Bundle extras) {
|
final void handleExtrasChanged(Bundle extras) {
|
||||||
mExtras = extras;
|
Bundle b = null;
|
||||||
onExtrasChanged(mExtras);
|
synchronized (mExtrasLock) {
|
||||||
|
mExtras = extras;
|
||||||
|
if (mExtras != null) {
|
||||||
|
b = new Bundle(mExtras);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onExtrasChanged(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user