Invoke service connection consumer outside the object lock
The consumer may contain arbitrary operations which may acquire the local lock again and lead to dead lock. Currently forEachConnection is only called from disconnectActivityFromServices which is very rare to be called (activity destroyed without unbind service). So a local copy should be fine. Bug: 275277537 Test: atest ActivityRecordTests#testActivityServiceConnectionsHolder Change-Id: If26a0cb9970cf5318cd0477adcc0fe07e98aaed9
This commit is contained in:
@@ -99,13 +99,15 @@ public class ActivityServiceConnectionsHolder<T> {
|
||||
}
|
||||
|
||||
public void forEachConnection(Consumer<T> consumer) {
|
||||
final ArraySet<T> connections;
|
||||
synchronized (mActivity) {
|
||||
if (mConnections == null || mConnections.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (int i = mConnections.size() - 1; i >= 0; i--) {
|
||||
consumer.accept(mConnections.valueAt(i));
|
||||
}
|
||||
connections = new ArraySet<>(mConnections);
|
||||
}
|
||||
for (int i = connections.size() - 1; i >= 0; i--) {
|
||||
consumer.accept(connections.valueAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2399,7 +2399,10 @@ public class ActivityRecordTests extends WindowTestsBase {
|
||||
holder.addConnection(connection);
|
||||
assertTrue(holder.isActivityVisible());
|
||||
final int[] count = new int[1];
|
||||
final Consumer<Object> c = conn -> count[0]++;
|
||||
final Consumer<Object> c = conn -> {
|
||||
count[0]++;
|
||||
assertFalse(Thread.holdsLock(activity));
|
||||
};
|
||||
holder.forEachConnection(c);
|
||||
assertEquals(1, count[0]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user