seperating callback changes
After some discussion amongst Telecom and an API council member, the
better design decision is to break up previous CallEventCallback into
two seperate callbacks.
The reason being, there is one set of callbacks that require the
client to complete a Consumer and another set of callbacks that only
provide event updates.
By making this change, the API surface becomes cleaner and should
eliminate some confusion.
bug: 268098087
Test: CTS
Change-Id: If5c46af9618be3720be203402bad9b583b3b2d06
diff --git a/telecomm/java/android/telecom/CallControlCallback.java b/telecomm/java/android/telecom/CallControlCallback.java
new file mode 100644
index 0000000..aadf337
--- /dev/null
+++ b/telecomm/java/android/telecom/CallControlCallback.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 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 android.telecom;
+
+import android.annotation.NonNull;
+
+import java.util.function.Consumer;
+
+/**
+ * CallControlCallback relays call updates (that require a response) from the Telecom framework out
+ * to the application.This can include operations which the app must implement on a Call due to the
+ * presence of other calls on the device, requests relayed from a Bluetooth device, or from another
+ * calling surface.
+ *
+ * <p>
+ * All CallControlCallbacks are transactional, meaning that a client must
+ * complete the {@link Consumer} via {@link Consumer#accept(Object)} in order to complete the
+ * CallControlCallbacks. If a CallControlCallbacks can be completed, the
+ * {@link Consumer#accept(Object)} should be called with {@link Boolean#TRUE}. Otherwise,
+ * {@link Consumer#accept(Object)} should be called with {@link Boolean#FALSE} to represent the
+ * CallControlCallbacks cannot be completed on the client side.
+ *
+ * <p>
+ * Note: Each CallEventCallback has a timeout of 5000 milliseconds. Failing to complete the
+ * {@link Consumer} before the timeout will result in a failed transaction.
+ */
+public interface CallControlCallback {
+ /**
+ * Telecom is informing the client to set the call active
+ *
+ * @param wasCompleted The {@link Consumer} to be completed. If the client can set the call
+ * active on their end, the {@link Consumer#accept(Object)} should be
+ * called with {@link Boolean#TRUE}. Otherwise,
+ * {@link Consumer#accept(Object)} should be called with
+ * {@link Boolean#FALSE}.
+ */
+ void onSetActive(@NonNull Consumer<Boolean> wasCompleted);
+
+ /**
+ * Telecom is informing the client to set the call inactive. This is the same as holding a call
+ * for two endpoints but can be extended to setting a meeting inactive.
+ *
+ * @param wasCompleted The {@link Consumer} to be completed. If the client can set the call
+ * inactive on their end, the {@link Consumer#accept(Object)} should be
+ * called with {@link Boolean#TRUE}. Otherwise,
+ * {@link Consumer#accept(Object)} should be called with
+ * {@link Boolean#FALSE}.
+ */
+ void onSetInactive(@NonNull Consumer<Boolean> wasCompleted);
+
+ /**
+ * Telecom is informing the client to answer an incoming call and set it to active.
+ *
+ * @param videoState see {@link android.telecom.CallAttributes.CallType} for valid states
+ * @param wasCompleted The {@link Consumer} to be completed. If the client can answer the call
+ * on their end, {@link Consumer#accept(Object)} should be called with
+ * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)} should
+ * be called with {@link Boolean#FALSE}.
+ */
+ void onAnswer(@android.telecom.CallAttributes.CallType int videoState,
+ @NonNull Consumer<Boolean> wasCompleted);
+
+ /**
+ * Telecom is informing the client to reject the incoming call
+ *
+ * @param wasCompleted The {@link Consumer} to be completed. If the client can reject the
+ * incoming call, {@link Consumer#accept(Object)} should be called with
+ * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)}
+ * should be called with {@link Boolean#FALSE}.
+ */
+ void onReject(@NonNull Consumer<Boolean> wasCompleted);
+
+ /**
+ * Telecom is informing the client to disconnect the call
+ *
+ * @param wasCompleted The {@link Consumer} to be completed. If the client can disconnect the
+ * call on their end, {@link Consumer#accept(Object)} should be called with
+ * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)}
+ * should be called with {@link Boolean#FALSE}.
+ */
+ void onDisconnect(@NonNull Consumer<Boolean> wasCompleted);
+
+ /**
+ * Telecom is informing the client to set the call in streaming.
+ *
+ * @param wasCompleted The {@link Consumer} to be completed. If the client can stream the
+ * call on their end, {@link Consumer#accept(Object)} should be called with
+ * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)}
+ * should be called with {@link Boolean#FALSE}.
+ */
+ void onCallStreamingStarted(@NonNull Consumer<Boolean> wasCompleted);
+}
diff --git a/telecomm/java/android/telecom/CallEventCallback.java b/telecomm/java/android/telecom/CallEventCallback.java
index 806febd..bfe3685 100644
--- a/telecomm/java/android/telecom/CallEventCallback.java
+++ b/telecomm/java/android/telecom/CallEventCallback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -16,108 +16,22 @@
package android.telecom;
-
import android.annotation.NonNull;
import java.util.List;
-import java.util.function.Consumer;
/**
- * CallEventCallback relays updates to a call from the Telecom framework.
- * This can include operations which the app must implement on a Call due to the presence of other
- * calls on the device, requests relayed from a Bluetooth device, or from another calling surface.
- *
- * <p>
- * CallEventCallbacks with {@link Consumer}s are transactional, meaning that a client must
- * complete the {@link Consumer} via {@link Consumer#accept(Object)} in order to complete the
- * CallEventCallback. If a CallEventCallback can be completed, the
- * {@link Consumer#accept(Object)} should be called with {@link Boolean#TRUE}. Otherwise,
- * {@link Consumer#accept(Object)} should be called with {@link Boolean#FALSE} to represent the
- * CallEventCallback cannot be completed on the client side.
- *
- * <p>
- * Note: Each CallEventCallback has a timeout of 5000 milliseconds. Failing to complete the
- * {@link Consumer} before the timeout will result in a failed transaction.
+ * CallEventCallback relays call updates (that do not require any action) from the Telecom framework
+ * out to the application. This can include operations which the app must implement on a Call due to
+ * the presence of other calls on the device, requests relayed from a Bluetooth device,
+ * or from another calling surface.
*/
public interface CallEventCallback {
/**
- * Telecom is informing the client to set the call active
- *
- * @param wasCompleted The {@link Consumer} to be completed. If the client can set the call
- * active on their end, the {@link Consumer#accept(Object)} should be
- * called with {@link Boolean#TRUE}. Otherwise,
- * {@link Consumer#accept(Object)} should be called with
- * {@link Boolean#FALSE}.
- */
- void onSetActive(@NonNull Consumer<Boolean> wasCompleted);
-
- /**
- * Telecom is informing the client to set the call inactive. This is the same as holding a call
- * for two endpoints but can be extended to setting a meeting inactive.
- *
- * @param wasCompleted The {@link Consumer} to be completed. If the client can set the call
- * inactive on their end, the {@link Consumer#accept(Object)} should be
- * called with {@link Boolean#TRUE}. Otherwise,
- * {@link Consumer#accept(Object)} should be called with
- * {@link Boolean#FALSE}.
- */
- void onSetInactive(@NonNull Consumer<Boolean> wasCompleted);
-
- /**
- * Telecom is informing the client to answer an incoming call and set it to active.
- *
- * @param videoState see {@link android.telecom.CallAttributes.CallType} for valid states
- * @param wasCompleted The {@link Consumer} to be completed. If the client can answer the call
- * on their end, {@link Consumer#accept(Object)} should be called with
- * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)} should
- * be called with {@link Boolean#FALSE}.
- */
- void onAnswer(@android.telecom.CallAttributes.CallType int videoState,
- @NonNull Consumer<Boolean> wasCompleted);
-
- /**
- * Telecom is informing the client to reject the incoming call
- *
- * @param wasCompleted The {@link Consumer} to be completed. If the client can reject the
- * incoming call, {@link Consumer#accept(Object)} should be called with
- * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)}
- * should be called with {@link Boolean#FALSE}.
- */
- void onReject(@NonNull Consumer<Boolean> wasCompleted);
-
- /**
- * Telecom is informing the client to disconnect the call
- *
- * @param wasCompleted The {@link Consumer} to be completed. If the client can disconnect the
- * call on their end, {@link Consumer#accept(Object)} should be called with
- * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)}
- * should be called with {@link Boolean#FALSE}.
- */
- void onDisconnect(@NonNull Consumer<Boolean> wasCompleted);
-
- /**
- * Telecom is informing the client to set the call in streaming.
- *
- * @param wasCompleted The {@link Consumer} to be completed. If the client can stream the
- * call on their end, {@link Consumer#accept(Object)} should be called with
- * {@link Boolean#TRUE}. Otherwise, {@link Consumer#accept(Object)}
- * should be called with {@link Boolean#FALSE}.
- */
- void onCallStreamingStarted(@NonNull Consumer<Boolean> wasCompleted);
-
- /**
- * Telecom is informing the client user requested call streaming but the stream can't be
- * started.
- *
- * @param reason Code to indicate the reason of this failure
- */
- void onCallStreamingFailed(@CallStreamingService.StreamingFailedReason int reason);
-
- /**
* Telecom is informing the client the current {@link CallEndpoint} changed.
*
* @param newCallEndpoint The new {@link CallEndpoint} through which call media flows
- * (i.e. speaker, bluetooth, etc.).
+ * (i.e. speaker, bluetooth, etc.).
*/
void onCallEndpointChanged(@NonNull CallEndpoint newCallEndpoint);
@@ -134,4 +48,12 @@
* @param isMuted The current mute state.
*/
void onMuteStateChanged(boolean isMuted);
+
+ /**
+ * Telecom is informing the client user requested call streaming but the stream can't be
+ * started.
+ *
+ * @param reason Code to indicate the reason of this failure
+ */
+ void onCallStreamingFailed(@CallStreamingService.StreamingFailedReason int reason);
}
diff --git a/telecomm/java/android/telecom/CallException.java b/telecomm/java/android/telecom/CallException.java
index d191593..e554082 100644
--- a/telecomm/java/android/telecom/CallException.java
+++ b/telecomm/java/android/telecom/CallException.java
@@ -30,7 +30,7 @@
/**
* This class defines exceptions that can be thrown when using Telecom APIs with
* {@link android.os.OutcomeReceiver}s. Most of these exceptions are thrown when changing a call
- * state with {@link CallControl}s or {@link CallEventCallback}s.
+ * state with {@link CallControl}s or {@link CallControlCallback}s.
*/
public final class CallException extends RuntimeException implements Parcelable {
/** @hide **/
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 20564d6..de99ebf 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -2669,8 +2669,10 @@
}
/**
- * Adds a new call with the specified {@link CallAttributes} to the telecom service. This method
- * can be used to add both incoming and outgoing calls.
+ * Reports a new call with the specified {@link CallAttributes} to the telecom service. This
+ * method can be used to report both incoming and outgoing calls. By reporting the call, the
+ * system is aware of the call and can provide updates on services (ex. Another device wants to
+ * disconnect the call) or events (ex. a new Bluetooth route became available).
*
* <p>
* The difference between this API call and {@link TelecomManager#placeCall(Uri, Bundle)} or
@@ -2693,9 +2695,20 @@
* <pre>
*
* // An app should first define their own construct of a Call that overrides all the
- * // {@link CallEventCallback}s
- * private class MyVoipCall implements CallEventCallback {
- * // override all the {@link CallEventCallback}s
+ * // {@link CallControlCallback}s and {@link CallEventCallback}s
+ * private class MyVoipCall {
+ * public String callId = "";
+ *
+ * public CallControlCallEventCallback handshakes = new
+ * CallControlCallEventCallback() {
+ * // override/ implement all {@link CallControlCallback}s
+ * }
+ * public CallEventCallback events = new
+ * CallEventCallback() {
+ * // override/ implement all {@link CallEventCallback}s
+ * }
+ * public MyVoipCall(String id){
+ * callId = id;
* }
*
* PhoneAccountHandle handle = new PhoneAccountHandle(
@@ -2707,28 +2720,33 @@
* "John Smith", Uri.fromParts("tel", "123", null))
* .build();
*
+ * MyVoipCall myFirstOutgoingCall = new MyVoipCall("1");
+ *
* telecomManager.addCall(callAttributes, Runnable::run, new OutcomeReceiver() {
* public void onResult(CallControl callControl) {
* // The call has been added successfully
* }
- * }, new MyVoipCall());
+ * }, myFirstOutgoingCall.handshakes, myFirstOutgoingCall.events);
* </pre>
*
* @param callAttributes attributes of the new call (incoming or outgoing, address, etc. )
* @param executor thread to run background CallEventCallback updates on
* @param pendingControl OutcomeReceiver that receives the result of addCall transaction
- * @param callEventCallback object that overrides CallEventCallback
+ * @param handshakes object that overrides {@link CallControlCallback}s
+ * @param events object that overrides {@link CallEventCallback}s
*/
@RequiresPermission(android.Manifest.permission.MANAGE_OWN_CALLS)
@SuppressLint("SamShouldBeLast")
public void addCall(@NonNull CallAttributes callAttributes,
@NonNull @CallbackExecutor Executor executor,
@NonNull OutcomeReceiver<CallControl, CallException> pendingControl,
- @NonNull CallEventCallback callEventCallback) {
+ @NonNull CallControlCallback handshakes,
+ @NonNull CallEventCallback events) {
Objects.requireNonNull(callAttributes);
Objects.requireNonNull(executor);
Objects.requireNonNull(pendingControl);
- Objects.requireNonNull(callEventCallback);
+ Objects.requireNonNull(handshakes);
+ Objects.requireNonNull(events);
ITelecomService service = getTelecomService();
if (service != null) {
@@ -2740,7 +2758,7 @@
// couple all the args passed by the client
String newCallId = transactionalServiceWrapper.trackCall(callAttributes, executor,
- pendingControl, callEventCallback);
+ pendingControl, handshakes, events);
// send args to server to process new call
service.addCall(callAttributes, transactionalServiceWrapper.getCallEventCallback(),