Merge cherrypicks of ['googleplex-android-review.googlesource.com/31157214', 'googleplex-android-review.googlesource.com/31395374'] into security-aosp-tm-release.

Change-Id: Ie35ea8f8c7fd2247b53c6a832cb6056f4b14ce53
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index d30216a..e7b84f1 100755
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -66,6 +66,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;
@@ -1395,11 +1396,21 @@
                         }
                     }
                 };
-                // 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 or shutdown");
+                }
                 try {
                     mServiceInterface.createConference(
                             call.getConnectionManagerPhoneAccount(),
@@ -1516,11 +1527,21 @@
                         }
                     }
                 };
-                // 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 or shutdown");
+                }
                 try {
                     mServiceInterface.createConnection(
                             call.getConnectionManagerPhoneAccount(),
diff --git a/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java b/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
index 02debcd..1b25441 100644
--- a/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
+++ b/src/com/android/server/telecom/callredirection/CallRedirectionProcessor.java
@@ -133,6 +133,14 @@
                             + mServiceType + " call redirection service");
                 }
             }
+            Log.i(this, "notifyTimeout: call redirection has timed out so "
+                    + "unbinding the connection");
+            if (mConnection != null) {
+                // We still need to call unbind even if the service disconnected.
+                mContext.unbindService(mConnection);
+                mConnection = null;
+            }
+            mService = null;
         }
 
         private class CallRedirectionServiceConnection implements ServiceConnection {
diff --git a/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java b/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
index f2fe045..9826f68 100644
--- a/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallRedirectionProcessorTest.java
@@ -219,6 +219,9 @@
         verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                 eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                 eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
+        // Verify service was unbound
+        verify(mContext, times(1)).
+                unbindService(any(ServiceConnection.class));
     }
 
     @Test
@@ -247,6 +250,9 @@
         verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                 eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                 eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+        // Verify service was unbound
+        verify(mContext, times(1)).
+                unbindService(any(ServiceConnection.class));
     }
 
     @Test
@@ -278,6 +284,9 @@
         verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                 eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                 eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+        // Verify service was unbound
+        verify(mContext, times(1)).
+                unbindService(any(ServiceConnection.class));
 
         // Wait for another carrier timeout time, but should not expect any carrier service request
         // is triggered.
@@ -287,6 +296,9 @@
         verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                 eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                 eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
+        // Verify service was unbound
+        verify(mContext, times(1)).
+                unbindService(any(ServiceConnection.class));
     }
 
     @Test