Add CtsConnectionService implementation.

Adding CtsConnection class and CtsConnectionService implementation.

Change-Id: I0458c1832fafb5fe34b2e1097f84ff44bd23470c
Test: THIS is a test.
Bug: 36098357
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java
new file mode 100644
index 0000000..0c7068b
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnection.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.cts.verifier.telecom;
+
+import android.telecom.Connection;
+import android.telecom.DisconnectCause;
+import android.telecom.VideoProfile;
+
+/**
+ * An implementation of the {@link android.telecom.Connection} class used by the
+ * {@link CtsConnectionService}.
+ */
+public class CtsConnection extends Connection {
+    /**
+     * Listener used to inform the CtsVerifier app of changes to a connection.
+     */
+    public static abstract class Listener {
+        void onDestroyed(CtsConnection connection) { };
+        void onDisconnect(CtsConnection connection) { };
+        void onHold(CtsConnection connection) { };
+        void onUnhold(CtsConnection connection) { };
+        void onAnswer(CtsConnection connection, int videoState) { };
+        void onReject(CtsConnection connection) { };
+        void onShowIncomingCallUi(CtsConnection connection) { };
+    }
+
+    private final boolean mIsIncomingCall;
+    private final Listener mListener;
+
+    public CtsConnection(boolean isIncomingCall, Listener listener) {
+        mIsIncomingCall = isIncomingCall;
+        mListener = listener;
+    }
+
+    public boolean isIncomingCall() {
+        return mIsIncomingCall;
+    }
+
+    @Override
+    public void onDisconnect() {
+        setDisconnectedAndDestroy(new DisconnectCause(DisconnectCause.LOCAL));
+
+        if (mListener != null) {
+            mListener.onDisconnect(this);
+        }
+    }
+
+
+    @Override
+    public void onHold() {
+        setOnHold();
+
+        if (mListener != null) {
+            mListener.onHold(this);
+        }
+    }
+
+    @Override
+    public void onUnhold() {
+        setActive();
+
+        if (mListener != null) {
+            mListener.onUnhold(this);
+        }
+    }
+
+    @Override
+    public void onAnswer(int videoState) {
+        setVideoState(videoState);
+        setActive();
+
+        if (mListener != null) {
+            mListener.onAnswer(this, videoState);
+        }
+    }
+
+    @Override
+    public void onAnswer() {
+        onAnswer(VideoProfile.STATE_AUDIO_ONLY);
+    }
+
+    @Override
+    public void onReject() {
+        setDisconnectedAndDestroy(new DisconnectCause(DisconnectCause.REJECTED));
+
+        if (mListener != null) {
+            mListener.onReject(this);
+        }
+    }
+
+    @Override
+    public void onShowIncomingCallUi() {
+        if (mListener != null) {
+            mListener.onShowIncomingCallUi(this);
+        }
+    }
+
+    private void setDisconnectedAndDestroy(DisconnectCause cause) {
+        setDisconnected(cause);
+        destroy();
+
+        if (mListener != null) {
+            mListener.onDestroyed(this);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
index 5ff3138..59949df 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/CtsConnectionService.java
@@ -16,12 +16,98 @@
 
 package com.android.cts.verifier.telecom;
 
+import android.content.Intent;
+import android.os.Bundle;
+import android.telecom.Connection;
+import android.telecom.ConnectionRequest;
 import android.telecom.ConnectionService;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * CTS Verifier ConnectionService implementation.
  */
 public class CtsConnectionService extends ConnectionService {
 
+    private CtsConnection.Listener mConnectionListener =
+            new CtsConnection.Listener() {
+                @Override
+                void onDestroyed(CtsConnection connection) {
+                    mConnections.remove(connection);
+                }
+            };
 
+    private static CtsConnectionService sConnectionService;
+
+    private List<CtsConnection> mConnections = new ArrayList<>();
+
+    public static CtsConnectionService getConnectionService() {
+        return sConnectionService;
+    }
+
+    public CtsConnectionService() throws Exception {
+        super();
+        sConnectionService = this;
+    }
+
+    public List<CtsConnection> getConnections() {
+        return mConnections;
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        sConnectionService = null;
+        return super.onUnbind(intent);
+    }
+
+    @Override
+    public Connection onCreateOutgoingConnection(PhoneAccountHandle connectionManagerAccount,
+                                                 final ConnectionRequest request) {
+
+        return createManagedConnection(request, false);
+    }
+
+    @Override
+    public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount,
+                                                 ConnectionRequest request) {
+
+        return createManagedConnection(request, true);
+    }
+
+    @Override
+    public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerHandle,
+                                                 ConnectionRequest request) {
+    }
+
+    @Override
+    public void onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerHandle,
+                                                 ConnectionRequest request) {
+    }
+
+    private Connection createManagedConnection(ConnectionRequest request, boolean isIncoming) {
+        boolean isSelfManaged = request.getAccountHandle().equals(
+                PhoneAccountUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE);
+
+        CtsConnection connection = new CtsConnection(isIncoming,
+                mConnectionListener);
+        if (isSelfManaged) {
+            connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED);
+        }
+        connection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORT_HOLD |
+                Connection.CAPABILITY_HOLD);
+        connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+        connection.setExtras(request.getExtras());
+
+        Bundle moreExtras = new Bundle();
+        moreExtras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
+                request.getAccountHandle());
+        connection.putExtras(moreExtras);
+        connection.setVideoState(request.getVideoState());
+
+        mConnections.add(connection);
+        return connection;
+    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java
index 4201ffd..428d827 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/PhoneAccountUtils.java
@@ -43,6 +43,20 @@
             .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
             .build();
 
+    public static final String TEST_SELF_MAANGED_PHONE_ACCOUNT_ID = "selfMgdTest";
+    public static final String TEST_SELF_MANAGED_PHONE_ACCOUNT_LABEL = "CTSVerifier";
+    public static final Uri TEST_SELF_MANAGED_PHONE_ACCOUNT_ADDRESS =
+            Uri.parse("sip:sekf@android.com");
+    public static final PhoneAccountHandle TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE =
+            new PhoneAccountHandle(new ComponentName(
+                    PassFailButtons.class.getPackage().getName(),
+                    CtsConnectionService.class.getName()), TEST_SELF_MAANGED_PHONE_ACCOUNT_ID);
+    public static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT = new PhoneAccount.Builder(
+            TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE, TEST_SELF_MANAGED_PHONE_ACCOUNT_LABEL)
+            .setAddress(TEST_SELF_MANAGED_PHONE_ACCOUNT_ADDRESS)
+            .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)
+            .build();
+
     /**
      * Registers the test phone account.
      * @param context The context.
@@ -73,4 +87,25 @@
                 Context.TELECOM_SERVICE);
         telecomManager.unregisterPhoneAccount(TEST_PHONE_ACCOUNT_HANDLE);
     }
+
+    /**
+     * Registers the test self-managed phone account.
+     * @param context The context.
+     */
+    public static void registerTestSelfManagedPhoneAccount(Context context) {
+        TelecomManager telecomManager = (TelecomManager) context.getSystemService(
+                Context.TELECOM_SERVICE);
+        telecomManager.registerPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT);
+    }
+
+    /**
+     * Retrieves the test phone account, or null if not registered.
+     * @param context The context.
+     * @return The Phone Account.
+     */
+    public static PhoneAccount getSelfManagedPhoneAccount(Context context) {
+        TelecomManager telecomManager = (TelecomManager) context.getSystemService(
+                Context.TELECOM_SERVICE);
+        return telecomManager.getPhoneAccount(TEST_SELF_MANAGED_PHONE_ACCOUNT_HANDLE);
+    }
 }