Add API for cross device calling.

Test: CTS test
Change-Id: I1a3aa6c1ae6d445a2f3b55e5f0d11918da5bed33
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 6279bf8..0bb40a7 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -54,8 +54,10 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.Executor;
 
 /**
@@ -586,6 +588,14 @@
             "android.telecom.extra.START_CALL_WITH_RTT";
 
     /**
+     * A parcelable extra, which when set on the bundle passed into {@link #placeCall(Uri, Bundle)},
+     * indicates that the call should be initiated with an active {@link CallEndpoint} to stream
+     * the call as a tethered call.
+     */
+    public static final String EXTRA_START_CALL_ON_ENDPOINT =
+            "android.telecom.extra.START_CALL_ON_ENDPOINT";
+
+    /**
      * Start an activity indicating that the completion of an outgoing call or an incoming call
      * which was not blocked by the {@link CallScreeningService}, and which was NOT terminated
      * while the call was in {@link Call#STATE_AUDIO_PROCESSING}.
@@ -745,6 +755,23 @@
             "android.telecom.INCLUDE_SELF_MANAGED_CALLS";
 
     /**
+     * A boolean meta-data value indicating this {@link InCallService} implementation is aimed at
+     * working as a streaming app for a tethered call. When there's a tethered call
+     * requesting to a {@link CallEndpoint} registered with this app, Telecom will bind to this
+     * streaming app and let the app streaming the call to the requested endpoint.
+     * <p>
+     * This meta-data can only be set for an {@link InCallService} which doesn't set neither
+     * {@link #METADATA_IN_CALL_SERVICE_UI} nor {@link #METADATA_IN_CALL_SERVICE_CAR_MODE_UI}.
+     * Otherwise, the app will be treated as a phone/dialer app or a car-mode app.
+     * <p>
+     * The {@link InCallService} declared this meta-data must implement
+     * {@link InCallService#onCallEndpointActivationRequested(CallEndpoint, CallEndpointSession)}.
+     * See this method for more information.
+     */
+    public static final String METADATA_STREAMING_TETHERED_CALLS =
+            "android.telecom.STREAMING_TETHERED_CALLS";
+
+    /**
      * The dual tone multi-frequency signaling character sent to indicate the dialing system should
      * pause for a predefined period.
      */
@@ -2250,6 +2277,7 @@
      *   <li>{@link #EXTRA_PHONE_ACCOUNT_HANDLE}</li>
      *   <li>{@link #EXTRA_START_CALL_WITH_SPEAKERPHONE}</li>
      *   <li>{@link #EXTRA_START_CALL_WITH_VIDEO_STATE}</li>
+     *   <li>{@link #EXTRA_START_CALL_ON_ENDPOINT}</li>
      * </ul>
      * <p>
      * An app which implements the self-managed {@link ConnectionService} API uses
@@ -2579,6 +2607,79 @@
         }
     }
 
+    /**
+     * Register a set of {@link CallEndpoint} to telecom. All registered {@link CallEndpoint} can
+     * be provided as options for push, place or answer call externally.
+     *
+     * @param endpoints Endpoints to be registered.
+     */
+    // TODO: add permission requirements
+    // @RequiresPermission{}
+    public void registerCallEndpoints(@NonNull Set<CallEndpoint> endpoints) {
+        ITelecomService service = getTelecomService();
+        List<CallEndpoint> endpointList = new ArrayList<>(endpoints);
+        if (service != null) {
+            try {
+                service.registerCallEndpoints(endpointList, mContext.getOpPackageName());
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException registerCallEndpoints: " + e);
+                e.rethrowAsRuntimeException();
+            }
+        } else {
+            throw new IllegalStateException("Telecom service is null.");
+        }
+    }
+
+    /**
+     * Unregister all {@link CallEndpoint} from telecom in the set provided. After un-registration,
+     * telecom will stop tracking and maintaining these {@link CallEndpoint}, user can no longer
+     * carry a call on them.
+     *
+     * @param endpoints
+     */
+    // TODO: add permission requirements
+    // @RequiresPermission{}
+    public void unregisterCallEndpoints(@NonNull Set<CallEndpoint> endpoints) {
+        ITelecomService service = getTelecomService();
+        List<CallEndpoint> endpointList = new ArrayList<>(endpoints);
+        if (service != null) {
+            try {
+                service.unregisterCallEndpoints(endpointList, mContext.getOpPackageName());
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException unregisterCallEndpoints: " + e);
+                e.rethrowAsRuntimeException();
+            }
+        } else {
+            throw new IllegalStateException("Telecom service is null.");
+        }
+    }
+
+    /**
+     * Return a set all registered {@link CallEndpoint} that can be used to stream and carry an
+     * external call.
+     *
+     * @return A set of all available {@link CallEndpoint}.
+     */
+    // TODO: add permission requirements
+    // @RequiresPermission{}
+    public @NonNull Set<CallEndpoint> getCallEndpoints() {
+        Set<CallEndpoint> endpoints = new HashSet<>();
+        List<CallEndpoint> endpointList;
+        ITelecomService service = getTelecomService();
+        if (service != null) {
+            try {
+                endpointList = service.getCallEndpoints(mContext.getOpPackageName());
+                return new HashSet<>(endpointList);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException registerCallEndpoints: " + e);
+                e.rethrowAsRuntimeException();
+            }
+        } else {
+            throw new IllegalStateException("Telecom service is null.");
+        }
+        return endpoints;
+    }
+
     private boolean isSystemProcess() {
         return Process.myUid() == Process.SYSTEM_UID;
     }