add capability to send and receive events
bug: 269512817
Test: CTS
Change-Id: I5f4561192b7c8ab978754e3a7da6549d35c61b1d
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index 2135e27..6b2bea0 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -147,10 +147,8 @@
* <li>{@link DisconnectCause#REJECTED}</li>
* <li>{@link DisconnectCause#MISSED}</li>
* </ul>
- *
* @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.
*
@@ -254,6 +252,36 @@
}
/**
+ * Raises an event to the {@link android.telecom.InCallService} implementations tracking this
+ * call via {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}.
+ * These events and the associated extra keys for the {@code Bundle} parameter are defined
+ * in Android X. This API is used to relay additional information about a call other than
+ * what is specified in the {@link android.telecom.CallAttributes} to
+ * {@link android.telecom.InCallService}s. This might include, for example, a change to the list
+ * of participants in a meeting, or the name of the speakers who have their hand raised. Where
+ * appropriate, the {@link InCallService}s tracking this call may choose to render this
+ * additional information about the call. An automotive calling UX, for example may have enough
+ * screen real estate to indicate the number of participants in a meeting, but to prevent
+ * distractions could suppress the list of participants.
+ *
+ * @param event that is defined in AndroidX (ex. The number of participants changed)
+ * @param extras the updated value in relation to the event (ex. 4 participants)
+ */
+ public void sendEvent(@NonNull String event, @NonNull Bundle extras) {
+ Objects.requireNonNull(event);
+ Objects.requireNonNull(extras);
+ if (mServerInterface != null) {
+ try {
+ mServerInterface.sendEvent(mCallId, event, extras);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ } else {
+ throw new IllegalStateException(INTERFACE_ERROR_MSG);
+ }
+ }
+
+ /**
* Since {@link OutcomeReceiver}s cannot be passed via AIDL, a ResultReceiver (which can) must
* wrap the Clients {@link OutcomeReceiver} passed in and await for the Telecom Server side
* response in {@link ResultReceiver#onReceiveResult(int, Bundle)}.
diff --git a/telecomm/java/android/telecom/CallEventCallback.java b/telecomm/java/android/telecom/CallEventCallback.java
index bfe3685..d96c406 100644
--- a/telecomm/java/android/telecom/CallEventCallback.java
+++ b/telecomm/java/android/telecom/CallEventCallback.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.NonNull;
+import android.os.Bundle;
import java.util.List;
@@ -56,4 +57,17 @@
* @param reason Code to indicate the reason of this failure
*/
void onCallStreamingFailed(@CallStreamingService.StreamingFailedReason int reason);
+
+ /**
+ * Informs this {@link android.telecom.CallEventCallback} on events raised from a
+ * {@link android.telecom.InCallService} presenting this call. The event key and extra values
+ * are defined in AndroidX. This enables alternative calling surfaces, such as an automotive
+ * UI, to relay requests to perform other non-standard call actions to the app. For example,
+ * an automotive calling solution may offer the ability for the user to raise their hand
+ * during a meeting.
+ *
+ * @param event that is defined in AndroidX (ex. the number of participants changed)
+ * @param extras the updated value in relation to the event (ex. 4 participants)
+ */
+ void onEvent(@NonNull String event, @NonNull Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
index 7bba1eb..e44e2b3 100644
--- a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
+++ b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
@@ -19,6 +19,7 @@
import static android.telecom.TelecomManager.TELECOM_TRANSACTION_SUCCESS;
import android.os.Binder;
+import android.os.Bundle;
import android.os.OutcomeReceiver;
import android.os.ResultReceiver;
import android.telecom.CallAttributes;
@@ -148,6 +149,7 @@
private static final String ON_AVAILABLE_CALL_ENDPOINTS = "onAvailableCallEndpointsChanged";
private static final String ON_MUTE_STATE_CHANGED = "onMuteStateChanged";
private static final String ON_CALL_STREAMING_FAILED = "onCallStreamingFailed";
+ private static final String ON_EVENT = "onEvent";
private void handleHandshakeCallback(String action, String callId, int code,
ResultReceiver ackResultReceiver) {
@@ -314,5 +316,23 @@
Log.i(TAG, TextUtils.formatSimple("oCSF: id=[%s], reason=[%s]", callId, reason));
handleEventCallback(callId, ON_CALL_STREAMING_FAILED, reason);
}
+
+ @Override
+ public void onEvent(String callId, String event, Bundle extras) {
+ // lookup the callEventCallback associated with the particular call
+ TransactionalCall call = mCallIdToTransactionalCall.get(callId);
+ if (call != null) {
+ CallEventCallback callback = call.getCallStateCallback();
+ Executor executor = call.getExecutor();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> {
+ callback.onEvent(event, extras);
+ });
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
};
}
diff --git a/telecomm/java/com/android/internal/telecom/ICallControl.aidl b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
index b78a77e..3e651e9 100644
--- a/telecomm/java/com/android/internal/telecom/ICallControl.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telecom;
+import android.os.Bundle;
import android.telecom.CallControl;
import android.telecom.CallEndpoint;
import android.telecom.DisconnectCause;
@@ -30,4 +31,5 @@
void disconnect(String callId, in DisconnectCause disconnectCause, in ResultReceiver callback);
void startCallStreaming(String callId, in ResultReceiver callback);
void requestCallEndpointChange(in CallEndpoint callEndpoint, in ResultReceiver callback);
+ void sendEvent(String callId, String event, in Bundle extras);
}
\ No newline at end of file
diff --git a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
index fef5e9e..dd61d17 100644
--- a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telecom;
+import android.os.Bundle;
import android.telecom.CallControl;
import android.telecom.CallEndpoint;
import com.android.internal.telecom.ICallControl;
@@ -44,6 +45,8 @@
void onCallEndpointChanged(String callId, in CallEndpoint endpoint);
void onAvailableCallEndpointsChanged(String callId, in List<CallEndpoint> endpoint);
void onMuteStateChanged(String callId, boolean isMuted);
+ // -- Events
+ void onEvent(String callId, String event, in Bundle extras);
// hidden methods that help with cleanup
void removeCallFromTransactionalServiceWrapper(String callId);
}
\ No newline at end of file