Add call streaming related API.
Bug: 262412844
Test: build, cts test
Change-Id: Ib9013291ba5bac4f94fb2919fb2eccb8aa25acb8
diff --git a/telecomm/java/android/telecom/CallStreamingService.java b/telecomm/java/android/telecom/CallStreamingService.java
new file mode 100644
index 0000000..affa6b6
--- /dev/null
+++ b/telecomm/java/android/telecom/CallStreamingService.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2022 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.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.telecom.ICallStreamingService;
+import com.android.internal.telecom.IStreamingCallAdapter;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This service is implemented by an app that wishes to provide functionality for a general call
+ * streaming sender for voip calls.
+ *
+ * TODO: add doc of how to be the general streaming sender
+ *
+ */
+public abstract class CallStreamingService extends Service {
+ /**
+ * The {@link android.content.Intent} that must be declared as handled by the service.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE = "android.telecom.CallStreamingService";
+
+ private static final int MSG_SET_STREAMING_CALL_ADAPTER = 1;
+ private static final int MSG_CALL_STREAMING_STARTED = 2;
+ private static final int MSG_CALL_STREAMING_STOPPED = 3;
+ private static final int MSG_CALL_STREAMING_CHANGED_CHANGED = 4;
+
+ /** Default Handler used to consolidate binder method calls onto a single thread. */
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ if (mStreamingCallAdapter == null && msg.what != MSG_SET_STREAMING_CALL_ADAPTER) {
+ return;
+ }
+
+ switch (msg.what) {
+ case MSG_SET_STREAMING_CALL_ADAPTER:
+ mStreamingCallAdapter = new StreamingCallAdapter(
+ (IStreamingCallAdapter) msg.obj);
+ break;
+ case MSG_CALL_STREAMING_STARTED:
+ mCall = (StreamingCall) msg.obj;
+ mCall.setAdapter(mStreamingCallAdapter);
+ CallStreamingService.this.onCallStreamingStarted(mCall);
+ break;
+ case MSG_CALL_STREAMING_STOPPED:
+ mCall = null;
+ mStreamingCallAdapter = null;
+ CallStreamingService.this.onCallStreamingStopped();
+ break;
+ case MSG_CALL_STREAMING_CHANGED_CHANGED:
+ int state = (int) msg.obj;
+ mCall.setStreamingState(state);
+ CallStreamingService.this.onCallStreamingStateChanged(state);
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+ @Nullable
+ @Override
+ public IBinder onBind(@NonNull Intent intent) {
+ return new CallStreamingServiceBinder();
+ }
+
+ /** Manages the binder calls so that the implementor does not need to deal with it. */
+ private final class CallStreamingServiceBinder extends ICallStreamingService.Stub {
+ @Override
+ public void setStreamingCallAdapter(IStreamingCallAdapter streamingCallAdapter)
+ throws RemoteException {
+ mHandler.obtainMessage(MSG_SET_STREAMING_CALL_ADAPTER, mStreamingCallAdapter)
+ .sendToTarget();
+ }
+
+ @Override
+ public void onCallStreamingStarted(StreamingCall call) throws RemoteException {
+ mHandler.obtainMessage(MSG_CALL_STREAMING_STARTED, call).sendToTarget();
+ }
+
+ @Override
+ public void onCallStreamingStopped() throws RemoteException {
+ mHandler.obtainMessage(MSG_CALL_STREAMING_STOPPED).sendToTarget();
+ }
+
+ @Override
+ public void onCallStreamingStateChanged(int state) throws RemoteException {
+ mHandler.obtainMessage(MSG_CALL_STREAMING_CHANGED_CHANGED, state).sendToTarget();
+ }
+ }
+
+ /**
+ * Call streaming request reject reason used with
+ * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
+ * call streaming request because there's an ongoing streaming call on this device.
+ */
+ public static final int STREAMING_FAILED_ALREADY_STREAMING = 1;
+
+ /**
+ * Call streaming request reject reason used with
+ * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
+ * call streaming request because telecom can't find existing general streaming sender on this
+ * device.
+ */
+ public static final int STREAMING_FAILED_NO_SENDER = 2;
+
+ /**
+ * Call streaming request reject reason used with
+ * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
+ * call streaming request because telecom can't bind to the general streaming sender app.
+ */
+ public static final int STREAMING_FAILED_SENDER_BINDING_ERROR = 3;
+
+ private StreamingCallAdapter mStreamingCallAdapter;
+ private StreamingCall mCall;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = {"STREAMING_FAILED"},
+ value = {
+ STREAMING_FAILED_ALREADY_STREAMING,
+ STREAMING_FAILED_NO_SENDER,
+ STREAMING_FAILED_SENDER_BINDING_ERROR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StreamingFailedReason {};
+
+ /**
+ * Called when a {@code StreamingCall} has been added to this call streaming session. The call
+ * streaming sender should start to intercept the device audio using audio records and audio
+ * tracks from Audio frameworks.
+ *
+ * @param call a newly added {@code StreamingCall}.
+ */
+ public void onCallStreamingStarted(@NonNull StreamingCall call) {
+ }
+
+ /**
+ * Called when a current {@code StreamingCall} has been removed from this call streaming
+ * session. The call streaming sender should notify the streaming receiver that the call is
+ * stopped streaming and stop the device audio interception.
+ */
+ public void onCallStreamingStopped() {
+ }
+
+ /**
+ * Called when the streaming state of current {@code StreamingCall} changed. General streaming
+ * sender usually get notified of the holding/unholding from the original owner voip app of the
+ * call.
+ */
+ public void onCallStreamingStateChanged(@StreamingCall.StreamingCallState int state) {
+ }
+}