Merge "Reduce latency for InCallUI by adding an intermediate state" into lmp-dev
diff --git a/src/com/android/telecomm/CreateConnectionProcessor.java b/src/com/android/telecomm/CreateConnectionProcessor.java
index 5a186f4..8ba73bf 100644
--- a/src/com/android/telecomm/CreateConnectionProcessor.java
+++ b/src/com/android/telecomm/CreateConnectionProcessor.java
@@ -18,6 +18,7 @@
 
 import android.telecomm.ConnectionRequest;
 import android.telecomm.ParcelableConnection;
+import android.telecomm.PhoneAccount;
 import android.telecomm.PhoneAccountHandle;
 import android.telephony.DisconnectCause;
 
@@ -78,10 +79,10 @@
         Log.v(this, "process");
         mAttemptRecords = new ArrayList<>();
         if (mCall.getTargetPhoneAccount() != null) {
-            mAttemptRecords.add(
-                    new CallAttemptRecord(mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
+            mAttemptRecords.add(new CallAttemptRecord(
+                    mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
         }
-        adjustAttemptsForWifi();
+        adjustAttemptsForConnectionManager();
         adjustAttemptsForEmergency();
         mAttemptRecordIterator = mAttemptRecords.iterator();
         attemptNextPhoneAccount();
@@ -134,28 +135,50 @@
         }
     }
 
-    // If there exists a registered Wi-Fi calling service, use it.
-    private void adjustAttemptsForWifi() {
-        switch (mAttemptRecords.size()) {
-            case 0:
-                return;
-            case 1:
-                break;
-            default:
-                Log.d(this, "Unexpectedly have > 1 attempt: %s", mAttemptRecords);
-                return;
+    private boolean shouldSetConnectionManager() {
+        if (mAttemptRecords.size() == 0) {
+            return false;
         }
-        PhoneAccountHandle simCallManager =
-                TelecommApp.getInstance().getPhoneAccountRegistrar().getSimCallManager();
 
-        Log.d(this, "adjustAttemptsForWifi finds simCallManager = %s", simCallManager);
-        if (simCallManager != null &&
-                !Objects.equals(simCallManager, mAttemptRecords.get(0).targetPhoneAccount)) {
-            mAttemptRecords.set(
-                    0,
-                    new CallAttemptRecord(
-                            simCallManager,
-                            mAttemptRecords.get(0).targetPhoneAccount));
+        if (mAttemptRecords.size() > 1) {
+            Log.d(this, "shouldSetConnectionManager, error, mAttemptRecords should not have more "
+                    + "than 1 record");
+            return false;
+        }
+
+        PhoneAccountRegistrar registrar = TelecommApp.getInstance().getPhoneAccountRegistrar();
+        PhoneAccountHandle connectionManager = registrar.getSimCallManager();
+        if (connectionManager == null) {
+            return false;
+        }
+
+        PhoneAccountHandle targetPhoneAccountHandle = mAttemptRecords.get(0).targetPhoneAccount;
+        if (Objects.equals(connectionManager, targetPhoneAccountHandle)) {
+            return false;
+        }
+
+        // Connection managers are only allowed to manage SIM subscriptions.
+        PhoneAccount targetPhoneAccount = registrar.getPhoneAccount(targetPhoneAccountHandle);
+        boolean isSimSubscription = (targetPhoneAccount.getCapabilities() &
+                PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0;
+        if (!isSimSubscription) {
+            return false;
+        }
+
+        return true;
+    }
+
+    // If there exists a registered connection manager then use it.
+    private void adjustAttemptsForConnectionManager() {
+        if (shouldSetConnectionManager()) {
+            CallAttemptRecord record = new CallAttemptRecord(
+                    TelecommApp.getInstance().getPhoneAccountRegistrar().getSimCallManager(),
+                    mAttemptRecords.get(0).targetPhoneAccount);
+            Log.v(this, "setConnectionManager, changing %s -> %s",
+                    mAttemptRecords.get(0).targetPhoneAccount, record);
+            mAttemptRecords.set(0, record);
+        } else {
+            Log.v(this, "setConnectionManager, not changing");
         }
     }
 
diff --git a/tests/src/com/android/telecomm/testapps/CallNotificationReceiver.java b/tests/src/com/android/telecomm/testapps/CallNotificationReceiver.java
index a8e3195..e941c2d 100644
--- a/tests/src/com/android/telecomm/testapps/CallNotificationReceiver.java
+++ b/tests/src/com/android/telecomm/testapps/CallNotificationReceiver.java
@@ -70,7 +70,7 @@
     private void sendIncomingCallIntent(Context context, boolean isVideoCall) {
         PhoneAccountHandle phoneAccount = new PhoneAccountHandle(
                 new ComponentName(context, TestConnectionService.class),
-                CallServiceNotifier.PHONE_ACCOUNT_ID);
+                CallServiceNotifier.CALL_PROVIDER_ID);
 
         // For the purposes of testing, indicate whether the incoming call is a video call by
         // stashing an indicator in the EXTRA_INCOMING_CALL_EXTRAS.
diff --git a/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java b/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java
index debfc9b..df66d0a 100644
--- a/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java
+++ b/tests/src/com/android/telecomm/testapps/CallServiceNotifier.java
@@ -40,7 +40,10 @@
 public class CallServiceNotifier {
     private static final CallServiceNotifier INSTANCE = new CallServiceNotifier();
 
-    static final String PHONE_ACCOUNT_ID = "testapps_TestConnectionService_Account_ID";
+    static final String CALL_PROVIDER_ID = "testapps_TestConnectionService_CALL_PROVIDER_ID";
+    static final String SIM_SUBSCRIPTION_ID = "testapps_TestConnectionService_SIM_SUBSCRIPTION_ID";
+    static final String CONNECTION_MANAGER_ID =
+            "testapps_TestConnectionService_CONNECTION_MANAGER_ID";
 
     /**
      * Static notification IDs.
@@ -92,26 +95,42 @@
     public void registerPhoneAccount(Context context) {
         TelecommManager telecommManager =
                 (TelecommManager) context.getSystemService(Context.TELECOMM_SERVICE);
+
+        telecommManager.clearAccounts(context.getPackageName());
+
+        // Register a call provider. This is used by 3rd party apps to provide voip calls.
         telecommManager.registerPhoneAccount(new PhoneAccount(
                 new PhoneAccountHandle(
                         new ComponentName(context, TestConnectionService.class),
-                        PHONE_ACCOUNT_ID),
+                        CALL_PROVIDER_ID),
                 Uri.parse("tel:555-TEST"),
                 "555-TEST",
                 PhoneAccount.CAPABILITY_CALL_PROVIDER,
                 R.drawable.stat_sys_phone_call,
-                "Dummy Service",
-                "a short description for the dummy service"));
+                "TelecommTestApp Call Provider",
+                "a short description for the call provider"));
+
+        telecommManager.registerPhoneAccount(new PhoneAccount(
+                new PhoneAccountHandle(
+                        new ComponentName(context, TestConnectionService.class),
+                        SIM_SUBSCRIPTION_ID),
+                Uri.parse("tel:555-TSIM"),
+                "555-TSIM",
+                PhoneAccount.CAPABILITY_CALL_PROVIDER | PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION,
+                R.drawable.stat_sys_phone_call,
+                "TelecommTestApp SIM Subscription",
+                "a short description for the sim subscription"));
+
         telecommManager.registerPhoneAccount(new PhoneAccount(
                 new PhoneAccountHandle(
                         new ComponentName(context, TestConnectionManager.class),
-                        PHONE_ACCOUNT_ID),
+                        CONNECTION_MANAGER_ID),
                 Uri.parse("tel:555-CMGR"),
                 "555-CMGR",
                 PhoneAccount.CAPABILITY_CONNECTION_MANAGER,
                 R.drawable.stat_sys_phone_call,
-                "Dummy Connection Manager",
-                "a short description for the dummy connection manager"));
+                "TelecommTestApp CONNECTION MANAGER",
+                "a short description for the connection manager"));
     }
 
     /**
diff --git a/tests/src/com/android/telecomm/testapps/TestConnectionManager.java b/tests/src/com/android/telecomm/testapps/TestConnectionManager.java
index 6a8433a..2ee953f 100644
--- a/tests/src/com/android/telecomm/testapps/TestConnectionManager.java
+++ b/tests/src/com/android/telecomm/testapps/TestConnectionManager.java
@@ -133,6 +133,11 @@
             mRemoteConnection.disconnect();
         }
 
+        @Override
+        public void onPlayDtmfTone(char c) {
+            mRemoteConnection.playDtmfTone(c);
+        }
+
         /** ${inheritDoc} */
         @Override
         public void onHold() {
diff --git a/tests/src/com/android/telecomm/testapps/TestConnectionService.java b/tests/src/com/android/telecomm/testapps/TestConnectionService.java
index bd9239b..6830803 100644
--- a/tests/src/com/android/telecomm/testapps/TestConnectionService.java
+++ b/tests/src/com/android/telecomm/testapps/TestConnectionService.java
@@ -153,10 +153,11 @@
         }
 
         void startOutgoing() {
+            setDialing();
             mHandler.postDelayed(new Runnable() {
                 @Override
                 public void run() {
-                    TestConnection.this.setActive();
+                    setActive();
                     activateCall(TestConnection.this);
                 }
             }, 4000);
@@ -192,6 +193,27 @@
 
         /** ${inheritDoc} */
         @Override
+        public void onPlayDtmfTone(char c) {
+             if (mRemoteConnection != null) {
+                mRemoteConnection.playDtmfTone(c);
+            } else {
+                if (c == '1') {
+                    setDialing();
+                }
+            }
+        }
+
+        /** ${inheritDoc} */
+        @Override
+        public void onStopDtmfTone() {
+             if (mRemoteConnection != null) {
+                mRemoteConnection.stopDtmfTone();
+            } else {
+            }
+        }
+
+        /** ${inheritDoc} */
+        @Override
         public void onDisconnect() {
             if (mRemoteConnection != null) {
                 mRemoteConnection.disconnect();
@@ -409,19 +431,7 @@
         // use a remote connection service.
         // TODO: Have a special phone number to test the account-picker dialog flow.
         if (number != null && number.startsWith("555")) {
-            // Normally we would use the original request as is, but for testing purposes, we are
-            // adding ".." to the end of the number to follow its path more easily through the logs.
-            final ConnectionRequest request = new ConnectionRequest(
-                    originalRequest.getAccountHandle(),
-                    originalRequest.getCallId(),
-                    Uri.fromParts(handle.getScheme(),
-                    handle.getSchemeSpecificPart() + "..", ""),
-                    originalRequest.getHandlePresentation(),
-                    originalRequest.getExtras(),
-                    originalRequest.getVideoState());
-
             mCalls.add(connection);
-
             connection.startOutgoing();
         } else {
             log("Not a test number");
diff --git a/tests/src/com/android/telecomm/testapps/TestVideoCallProvider.java b/tests/src/com/android/telecomm/testapps/TestVideoCallProvider.java
index 2aca2fa..94d0618 100644
--- a/tests/src/com/android/telecomm/testapps/TestVideoCallProvider.java
+++ b/tests/src/com/android/telecomm/testapps/TestVideoCallProvider.java
@@ -82,9 +82,8 @@
         mCameraId = cameraId;
 
         stopCamera();
-        // Get the capabilities of the camera and send it back to the in-call UI.
+        // Get the capabilities of the camera
         setCameraCapabilities(mCameraId);
-        changeCameraCapabilities(mCameraCapabilities);
     }
 
     @Override