Add lock on mCallbacks in ServiceBinder
Add locking for access to mCallbacks to avoid concurrent modification
shenanigans.
Change-Id: I66eb84cb5c3396b2325f7ea2bb870d3afb9ead86
Fixes: 122085348
Test: manual
diff --git a/src/com/android/server/telecom/ServiceBinder.java b/src/com/android/server/telecom/ServiceBinder.java
index cf5407d..a322a5e 100644
--- a/src/com/android/server/telecom/ServiceBinder.java
+++ b/src/com/android/server/telecom/ServiceBinder.java
@@ -73,13 +73,15 @@
// Reset any abort request if we're asked to bind again.
clearAbort();
- if (!mCallbacks.isEmpty()) {
- // Binding already in progress, append to the list of callbacks and bail out.
+ synchronized (mCallbacks) {
+ if (!mCallbacks.isEmpty()) {
+ // Binding already in progress, append to the list of callbacks and bail out.
+ mCallbacks.add(callback);
+ return;
+ }
mCallbacks.add(callback);
- return;
}
- mCallbacks.add(callback);
if (mServiceConnection == null) {
Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
ServiceConnection connection = new ServiceBinderConnection(call);
@@ -351,10 +353,16 @@
* outstanding callbacks is cleared afterwards.
*/
private void handleSuccessfulConnection() {
- for (BindCallback callback : mCallbacks) {
+ // Make a copy so that we don't have a deadlock inside one of the callbacks.
+ Set<BindCallback> callbacksCopy = new ArraySet<>();
+ synchronized (mCallbacks) {
+ callbacksCopy.addAll(mCallbacks);
+ mCallbacks.clear();
+ }
+
+ for (BindCallback callback : callbacksCopy) {
callback.onSuccess();
}
- mCallbacks.clear();
}
/**
@@ -362,10 +370,16 @@
* outstanding callbacks is cleared afterwards.
*/
private void handleFailedConnection() {
- for (BindCallback callback : mCallbacks) {
+ // Make a copy so that we don't have a deadlock inside one of the callbacks.
+ Set<BindCallback> callbacksCopy = new ArraySet<>();
+ synchronized (mCallbacks) {
+ callbacksCopy.addAll(mCallbacks);
+ mCallbacks.clear();
+ }
+
+ for (BindCallback callback : callbacksCopy) {
callback.onFailure();
}
- mCallbacks.clear();
}
/**