summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Riddle Hsu <riddlehsu@google.com> 2023-04-17 15:20:30 +0800
committer Riddle Hsu <riddlehsu@google.com> 2023-04-18 05:15:18 +0000
commit78fe2d8e4207ba556d46290921235a5518a66e01 (patch)
treea164cc9053d8101d0c4e4882059a41005f54385c
parent0bb91e1d18ee4857252fe61384c7aebb014747c9 (diff)
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
-rw-r--r--services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java5
2 files changed, 9 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
index 5f56af7fd4e0..1208b6ef396f 100644
--- a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
+++ b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
@@ -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));
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8f2b470908c4..0033e3e368c6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -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]);