Add connection manager fallback

With this CL we fallback to not using a connection manager in
two cases:
  - if the connection manager disconnects a call with
    CONNECTION_MANAGER_NOT_SUPPORTED
  - or if the connection manager crashed while creating the connection

Bug: 16903083
Change-Id: I05822991c5c34ca3533652a10fbcb8845a604925
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index fab2679..67c63a0 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -89,6 +89,7 @@
     private DisconnectCause mLastErrorDisconnectCause;
     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
     private final Context mContext;
+    private boolean mShouldUseConnectionManager = true;
 
     CreateConnectionProcessor(
             Call call, ConnectionServiceRepository repository, CreateConnectionResponse response,
@@ -185,6 +186,10 @@
     }
 
     private boolean shouldSetConnectionManager() {
+        if (!mShouldUseConnectionManager) {
+            return false;
+        }
+
         if (mAttemptRecords.size() == 0) {
             return false;
         }
@@ -307,12 +312,44 @@
             }
         }
 
+        private boolean shouldFallbackToNoConnectionManager(DisconnectCause cause) {
+            PhoneAccountHandle handle = mCall.getConnectionManagerPhoneAccount();
+            if (handle == null || !handle.equals(mPhoneAccountRegistrar.getSimCallManager())) {
+                return false;
+            }
+
+            ConnectionServiceWrapper connectionManager = mCall.getConnectionService();
+            if (connectionManager == null) {
+                return false;
+            }
+
+            if (cause.getCode() == DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED) {
+                Log.d(CreateConnectionProcessor.this, "Connection manager declined to handle the "
+                        + "call, falling back to not using a connection manager");
+                return true;
+            }
+
+            if (!connectionManager.isServiceValid("createConnection")) {
+                Log.d(CreateConnectionProcessor.this, "Connection manager unbound while trying "
+                        + "create a connection, falling back to not using a connection manager");
+                return true;
+            }
+
+            return false;
+        }
+
         @Override
         public void handleCreateConnectionFailure(DisconnectCause errorDisconnectCause) {
             // Failure of some sort; record the reasons for failure and try again if possible
             Log.d(CreateConnectionProcessor.this, "Connection failed: (%s)", errorDisconnectCause);
             mLastErrorDisconnectCause = errorDisconnectCause;
-            attemptNextPhoneAccount();
+            if (shouldFallbackToNoConnectionManager(errorDisconnectCause)) {
+                mShouldUseConnectionManager = false;
+                // Restart from the beginning.
+                process();
+            } else {
+                attemptNextPhoneAccount();
+            }
         }
     }
 }