blob: 581cd7ee6d50bbda697021b3279131848aaada20 [file] [log] [blame]
Grace Jiaef5a4cc2022-12-13 11:08:55 -08001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.telecom;
18
19import android.annotation.IntDef;
20import android.annotation.NonNull;
21import android.annotation.SdkConstant;
Grace Jiaacd4dad2023-01-17 18:14:36 -080022import android.annotation.SystemApi;
Grace Jiaef5a4cc2022-12-13 11:08:55 -080023import android.app.Service;
24import android.content.Intent;
25import android.os.Handler;
26import android.os.IBinder;
27import android.os.Looper;
28import android.os.Message;
29import android.os.RemoteException;
30
31import androidx.annotation.Nullable;
32
33import com.android.internal.telecom.ICallStreamingService;
34import com.android.internal.telecom.IStreamingCallAdapter;
35
36import java.lang.annotation.Retention;
37import java.lang.annotation.RetentionPolicy;
38
39/**
40 * This service is implemented by an app that wishes to provide functionality for a general call
41 * streaming sender for voip calls.
Grace Jiaacd4dad2023-01-17 18:14:36 -080042 * <p>
43 * Below is an example manifest registration for a {@code CallStreamingService}.
44 * <pre>
45 * {@code
46 * <service android:name=".EgCallStreamingService"
47 * android:permission="android.permission.BIND_CALL_STREAMING_SERVICE" >
48 * ...
49 * <intent-filter>
50 * <action android:name="android.telecom.CallStreamingService" />
51 * </intent-filter>
52 * </service>
53 * }
54 * </pre>
Thomas Stuart6e377852023-04-18 16:54:52 -070055 *
Grace Jiaacd4dad2023-01-17 18:14:36 -080056 * @hide
Grace Jiaef5a4cc2022-12-13 11:08:55 -080057 */
Grace Jiaacd4dad2023-01-17 18:14:36 -080058@SystemApi
Grace Jiaef5a4cc2022-12-13 11:08:55 -080059public abstract class CallStreamingService extends Service {
60 /**
61 * The {@link android.content.Intent} that must be declared as handled by the service.
62 */
63 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
64 public static final String SERVICE_INTERFACE = "android.telecom.CallStreamingService";
65
66 private static final int MSG_SET_STREAMING_CALL_ADAPTER = 1;
67 private static final int MSG_CALL_STREAMING_STARTED = 2;
68 private static final int MSG_CALL_STREAMING_STOPPED = 3;
Thomas Stuart6e377852023-04-18 16:54:52 -070069 private static final int MSG_CALL_STREAMING_STATE_CHANGED = 4;
Grace Jiaef5a4cc2022-12-13 11:08:55 -080070
71 /** Default Handler used to consolidate binder method calls onto a single thread. */
72 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
73 @Override
74 public void handleMessage(Message msg) {
75 if (mStreamingCallAdapter == null && msg.what != MSG_SET_STREAMING_CALL_ADAPTER) {
Tyler Gunn8ae42772023-04-26 02:41:41 +000076 Log.i(this, "handleMessage: null adapter!");
Grace Jiaef5a4cc2022-12-13 11:08:55 -080077 return;
78 }
79
80 switch (msg.what) {
81 case MSG_SET_STREAMING_CALL_ADAPTER:
Thomas Stuart6e377852023-04-18 16:54:52 -070082 if (msg.obj != null) {
Tyler Gunn8ae42772023-04-26 02:41:41 +000083 Log.i(this, "MSG_SET_STREAMING_CALL_ADAPTER");
Thomas Stuart6e377852023-04-18 16:54:52 -070084 mStreamingCallAdapter = new StreamingCallAdapter(
85 (IStreamingCallAdapter) msg.obj);
86 }
Grace Jiaef5a4cc2022-12-13 11:08:55 -080087 break;
88 case MSG_CALL_STREAMING_STARTED:
Tyler Gunn8ae42772023-04-26 02:41:41 +000089 Log.i(this, "MSG_CALL_STREAMING_STARTED");
Grace Jiaef5a4cc2022-12-13 11:08:55 -080090 mCall = (StreamingCall) msg.obj;
91 mCall.setAdapter(mStreamingCallAdapter);
92 CallStreamingService.this.onCallStreamingStarted(mCall);
93 break;
94 case MSG_CALL_STREAMING_STOPPED:
Tyler Gunn8ae42772023-04-26 02:41:41 +000095 Log.i(this, "MSG_CALL_STREAMING_STOPPED");
Grace Jiaef5a4cc2022-12-13 11:08:55 -080096 mCall = null;
97 mStreamingCallAdapter = null;
98 CallStreamingService.this.onCallStreamingStopped();
99 break;
Thomas Stuart6e377852023-04-18 16:54:52 -0700100 case MSG_CALL_STREAMING_STATE_CHANGED:
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800101 int state = (int) msg.obj;
Thomas Stuart6e377852023-04-18 16:54:52 -0700102 if (mStreamingCallAdapter != null) {
103 mCall.requestStreamingState(state);
104 CallStreamingService.this.onCallStreamingStateChanged(state);
105 }
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800106 break;
107 default:
108 break;
109 }
110 }
111 };
112
113 @Nullable
114 @Override
115 public IBinder onBind(@NonNull Intent intent) {
Tyler Gunn8ae42772023-04-26 02:41:41 +0000116 Log.i(this, "onBind");
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800117 return new CallStreamingServiceBinder();
118 }
119
120 /** Manages the binder calls so that the implementor does not need to deal with it. */
121 private final class CallStreamingServiceBinder extends ICallStreamingService.Stub {
122 @Override
123 public void setStreamingCallAdapter(IStreamingCallAdapter streamingCallAdapter)
124 throws RemoteException {
Tyler Gunn8ae42772023-04-26 02:41:41 +0000125 Log.i(this, "setCallStreamingAdapter");
126 mHandler.obtainMessage(MSG_SET_STREAMING_CALL_ADAPTER, streamingCallAdapter)
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800127 .sendToTarget();
128 }
129
130 @Override
131 public void onCallStreamingStarted(StreamingCall call) throws RemoteException {
Tyler Gunn8ae42772023-04-26 02:41:41 +0000132 Log.i(this, "onCallStreamingStarted");
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800133 mHandler.obtainMessage(MSG_CALL_STREAMING_STARTED, call).sendToTarget();
134 }
135
136 @Override
137 public void onCallStreamingStopped() throws RemoteException {
138 mHandler.obtainMessage(MSG_CALL_STREAMING_STOPPED).sendToTarget();
139 }
140
141 @Override
142 public void onCallStreamingStateChanged(int state) throws RemoteException {
Thomas Stuart6e377852023-04-18 16:54:52 -0700143 mHandler.obtainMessage(MSG_CALL_STREAMING_STATE_CHANGED, state).sendToTarget();
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800144 }
145 }
146
147 /**
148 * Call streaming request reject reason used with
149 * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
Grace Jiaacd4dad2023-01-17 18:14:36 -0800150 * call streaming request due to unknown reason.
151 */
152 public static final int STREAMING_FAILED_UNKNOWN = 0;
153
154 /**
155 * Call streaming request reject reason used with
156 * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800157 * call streaming request because there's an ongoing streaming call on this device.
158 */
159 public static final int STREAMING_FAILED_ALREADY_STREAMING = 1;
160
161 /**
162 * Call streaming request reject reason used with
163 * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
164 * call streaming request because telecom can't find existing general streaming sender on this
165 * device.
166 */
167 public static final int STREAMING_FAILED_NO_SENDER = 2;
168
169 /**
170 * Call streaming request reject reason used with
171 * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
172 * call streaming request because telecom can't bind to the general streaming sender app.
173 */
174 public static final int STREAMING_FAILED_SENDER_BINDING_ERROR = 3;
175
176 private StreamingCallAdapter mStreamingCallAdapter;
177 private StreamingCall mCall;
178
179 /**
180 * @hide
181 */
182 @IntDef(prefix = {"STREAMING_FAILED"},
183 value = {
Grace Jiaacd4dad2023-01-17 18:14:36 -0800184 STREAMING_FAILED_UNKNOWN,
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800185 STREAMING_FAILED_ALREADY_STREAMING,
186 STREAMING_FAILED_NO_SENDER,
187 STREAMING_FAILED_SENDER_BINDING_ERROR
Thomas Stuart6e377852023-04-18 16:54:52 -0700188 })
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800189 @Retention(RetentionPolicy.SOURCE)
Thomas Stuart6e377852023-04-18 16:54:52 -0700190 public @interface StreamingFailedReason {
191 }
192
193 ;
Grace Jiaef5a4cc2022-12-13 11:08:55 -0800194
195 /**
196 * Called when a {@code StreamingCall} has been added to this call streaming session. The call
197 * streaming sender should start to intercept the device audio using audio records and audio
198 * tracks from Audio frameworks.
199 *
200 * @param call a newly added {@code StreamingCall}.
201 */
202 public void onCallStreamingStarted(@NonNull StreamingCall call) {
203 }
204
205 /**
206 * Called when a current {@code StreamingCall} has been removed from this call streaming
207 * session. The call streaming sender should notify the streaming receiver that the call is
208 * stopped streaming and stop the device audio interception.
209 */
210 public void onCallStreamingStopped() {
211 }
212
213 /**
214 * Called when the streaming state of current {@code StreamingCall} changed. General streaming
215 * sender usually get notified of the holding/unholding from the original owner voip app of the
216 * call.
217 */
218 public void onCallStreamingStateChanged(@StreamingCall.StreamingCallState int state) {
219 }
220}