add CallControl#answerCall

After reviewing the API as a team more, we have decided to
add CallControl#answerCall to make CallControl more symmetric
to CallEventCallback.

bug: 268259965
Test: CTS
Change-Id: Ib48cd09002e1ee4522fe0439bf0c79a00ffa43da
diff --git a/core/api/current.txt b/core/api/current.txt
index fcec790..74d1800 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -42055,6 +42055,7 @@
   }
 
   public final class CallControl {
+    method public void answer(int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
     method public void disconnect(@NonNull android.telecom.DisconnectCause, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
     method @NonNull public android.os.ParcelUuid getCallId();
     method public void requestCallEndpointChange(@NonNull android.telecom.CallEndpoint, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index 6b2bea0..97538c1 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -76,7 +76,10 @@
     }
 
     /**
-     * Request Telecom set the call state to active.
+     * Request Telecom set the call state to active. This method should be called when either an
+     * outgoing call is ready to go active or a held call is ready to go active again. For incoming
+     * calls that are ready to be answered, use
+     * {@link CallControl#answer(int, Executor, OutcomeReceiver)}.
      *
      * @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
      *                 will be called on.
@@ -106,6 +109,43 @@
     }
 
     /**
+     * Request Telecom answer an incoming call.  For outgoing calls and calls that have been placed
+     * on hold, use {@link CallControl#setActive(Executor, OutcomeReceiver)}.
+     *
+     * @param videoState to report to Telecom. Telecom will store VideoState in the event another
+     *                   service/device requests it in order to continue the call on another screen.
+     * @param executor   The {@link Executor} on which the {@link OutcomeReceiver} callback
+     *                   will be called on.
+     * @param callback   that will be completed on the Telecom side that details success or failure
+     *                   of the requested operation.
+     *
+     *                   {@link OutcomeReceiver#onResult} will be called if Telecom has successfully
+     *                   switched the call state to active
+     *
+     *                   {@link OutcomeReceiver#onError} will be called if Telecom has failed to set
+     *                   the call state to active.  A {@link CallException} will be passed
+     *                   that details why the operation failed.
+     */
+    public void answer(@android.telecom.CallAttributes.CallType int videoState,
+            @CallbackExecutor @NonNull Executor executor,
+            @NonNull OutcomeReceiver<Void, CallException> callback) {
+        validateVideoState(videoState);
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+        if (mServerInterface != null) {
+            try {
+                mServerInterface.answer(videoState, mCallId,
+                        new CallControlResultReceiver("answer", executor, callback));
+
+            } catch (RemoteException e) {
+                throw e.rethrowAsRuntimeException();
+            }
+        } else {
+            throw new IllegalStateException(INTERFACE_ERROR_MSG);
+        }
+    }
+
+    /**
      * Request Telecom set the call state to inactive. This the same as hold for two call endpoints
      * but can be extended to setting a meeting to inactive.
      *
@@ -343,4 +383,13 @@
         }
     }
 
+    /** @hide */
+    private void validateVideoState(@android.telecom.CallAttributes.CallType int videoState) {
+        if (videoState != CallAttributes.AUDIO_CALL && videoState != CallAttributes.VIDEO_CALL) {
+            throw new IllegalArgumentException(TextUtils.formatSimple(
+                    "The VideoState argument passed in, %d , is not a valid VideoState. The "
+                            + "VideoState choices are limited to CallAttributes.AUDIO_CALL or"
+                            + "CallAttributes.VIDEO_CALL", videoState));
+        }
+    }
 }
diff --git a/telecomm/java/com/android/internal/telecom/ICallControl.aidl b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
index 3e651e9..5e2c923 100644
--- a/telecomm/java/com/android/internal/telecom/ICallControl.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
@@ -27,6 +27,7 @@
  */
 oneway interface ICallControl {
     void setActive(String callId, in ResultReceiver callback);
+    void answer(int videoState, String callId, in ResultReceiver callback);
     void setInactive(String callId, in ResultReceiver callback);
     void disconnect(String callId, in DisconnectCause disconnectCause, in ResultReceiver callback);
     void startCallStreaming(String callId, in ResultReceiver callback);