Ensure ScheduledExecutor is not shutdown before scheduling timeout cleanup.
The scheduled executor in ConnectionServiceWrapper may be shutdown when calling createConference and createCall. This is infrequently causing a `RejectedExecutionException`. This CL adds a check that mScheduledExecutor is not shutdown before scheduling the cleanup.
Flag: EXEMPT Security High/Critical Severity CVE
Bug: 388588560
Test: manually using the provided apk + atest CallsManagerTest
Change-Id: I0aaa0f7f57b8dd137403b6ceb7068e7c99652e1f
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index f2becbb..0f33f71 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -79,6 +79,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -1660,14 +1661,20 @@
}
}
};
- if (mScheduledExecutor != null) {
- // Post cleanup to the executor service and cache the future,
- // so we can cancel it if needed.
- ScheduledFuture<?> future = mScheduledExecutor.schedule(
- r.getRunnableToCancel(),SERVICE_BINDING_TIMEOUT, TimeUnit.MILLISECONDS);
- mScheduledFutureMap.put(call, future);
+ if (mScheduledExecutor != null && !mScheduledExecutor.isShutdown()) {
+ try {
+ // Post cleanup to the executor service and cache the future,
+ // so we can cancel it if needed.
+ ScheduledFuture<?> future = mScheduledExecutor.schedule(
+ r.getRunnableToCancel(),SERVICE_BINDING_TIMEOUT,
+ TimeUnit.MILLISECONDS);
+ mScheduledFutureMap.put(call, future);
+ } catch (RejectedExecutionException e) {
+ Log.e(this, e, "createConference: mScheduledExecutor was "
+ + "already shutdown");
+ }
} else {
- Log.w(this, "createConference: Scheduled executor is null");
+ Log.w(this, "createConference: Scheduled executor is null or shutdown");
mAnomalyReporter.reportAnomaly(
NULL_SCHEDULED_EXECUTOR_ERROR_UUID,
NULL_SCHEDULED_EXECUTOR_ERROR_MSG);
@@ -1796,14 +1803,20 @@
}
}
};
- if (mScheduledExecutor != null) {
- // Post cleanup to the executor service and cache the future,
- // so we can cancel it if needed.
- ScheduledFuture<?> future = mScheduledExecutor.schedule(
- r.getRunnableToCancel(),SERVICE_BINDING_TIMEOUT, TimeUnit.MILLISECONDS);
- mScheduledFutureMap.put(call, future);
+ if (mScheduledExecutor != null && !mScheduledExecutor.isShutdown()) {
+ try {
+ // Post cleanup to the executor service and cache the future,
+ // so we can cancel it if needed.
+ ScheduledFuture<?> future = mScheduledExecutor.schedule(
+ r.getRunnableToCancel(),SERVICE_BINDING_TIMEOUT,
+ TimeUnit.MILLISECONDS);
+ mScheduledFutureMap.put(call, future);
+ } catch (RejectedExecutionException e) {
+ Log.e(this, e, "createConnection: mScheduledExecutor was "
+ + "already shutdown");
+ }
} else {
- Log.w(this, "createConnection: Scheduled executor is null");
+ Log.w(this, "createConnection: Scheduled executor is null or shutdown");
mAnomalyReporter.reportAnomaly(
NULL_SCHEDULED_EXECUTOR_ERROR_UUID,
NULL_SCHEDULED_EXECUTOR_ERROR_MSG);