blob: 7f1112830222148ce8a4004cfcb209ea51327dd5 [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;
22import android.app.Service;
23import android.content.Intent;
24import android.os.Handler;
25import android.os.IBinder;
26import android.os.Looper;
27import android.os.Message;
28import android.os.RemoteException;
29
30import androidx.annotation.Nullable;
31
32import com.android.internal.telecom.ICallStreamingService;
33import com.android.internal.telecom.IStreamingCallAdapter;
34
35import java.lang.annotation.Retention;
36import java.lang.annotation.RetentionPolicy;
37
38/**
39 * This service is implemented by an app that wishes to provide functionality for a general call
40 * streaming sender for voip calls.
41 *
42 * TODO: add doc of how to be the general streaming sender
43 *
44 */
45public abstract class CallStreamingService extends Service {
46 /**
47 * The {@link android.content.Intent} that must be declared as handled by the service.
48 */
49 @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
50 public static final String SERVICE_INTERFACE = "android.telecom.CallStreamingService";
51
52 private static final int MSG_SET_STREAMING_CALL_ADAPTER = 1;
53 private static final int MSG_CALL_STREAMING_STARTED = 2;
54 private static final int MSG_CALL_STREAMING_STOPPED = 3;
55 private static final int MSG_CALL_STREAMING_CHANGED_CHANGED = 4;
56
57 /** Default Handler used to consolidate binder method calls onto a single thread. */
58 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
59 @Override
60 public void handleMessage(Message msg) {
61 if (mStreamingCallAdapter == null && msg.what != MSG_SET_STREAMING_CALL_ADAPTER) {
62 return;
63 }
64
65 switch (msg.what) {
66 case MSG_SET_STREAMING_CALL_ADAPTER:
67 mStreamingCallAdapter = new StreamingCallAdapter(
68 (IStreamingCallAdapter) msg.obj);
69 break;
70 case MSG_CALL_STREAMING_STARTED:
71 mCall = (StreamingCall) msg.obj;
72 mCall.setAdapter(mStreamingCallAdapter);
73 CallStreamingService.this.onCallStreamingStarted(mCall);
74 break;
75 case MSG_CALL_STREAMING_STOPPED:
76 mCall = null;
77 mStreamingCallAdapter = null;
78 CallStreamingService.this.onCallStreamingStopped();
79 break;
80 case MSG_CALL_STREAMING_CHANGED_CHANGED:
81 int state = (int) msg.obj;
Grace Jiaefb63a72023-01-19 14:15:25 -080082 mCall.requestStreamingState(state);
Grace Jiaef5a4cc2022-12-13 11:08:55 -080083 CallStreamingService.this.onCallStreamingStateChanged(state);
84 break;
85 default:
86 break;
87 }
88 }
89 };
90
91 @Nullable
92 @Override
93 public IBinder onBind(@NonNull Intent intent) {
94 return new CallStreamingServiceBinder();
95 }
96
97 /** Manages the binder calls so that the implementor does not need to deal with it. */
98 private final class CallStreamingServiceBinder extends ICallStreamingService.Stub {
99 @Override
100 public void setStreamingCallAdapter(IStreamingCallAdapter streamingCallAdapter)
101 throws RemoteException {
102 mHandler.obtainMessage(MSG_SET_STREAMING_CALL_ADAPTER, mStreamingCallAdapter)
103 .sendToTarget();
104 }
105
106 @Override
107 public void onCallStreamingStarted(StreamingCall call) throws RemoteException {
108 mHandler.obtainMessage(MSG_CALL_STREAMING_STARTED, call).sendToTarget();
109 }
110
111 @Override
112 public void onCallStreamingStopped() throws RemoteException {
113 mHandler.obtainMessage(MSG_CALL_STREAMING_STOPPED).sendToTarget();
114 }
115
116 @Override
117 public void onCallStreamingStateChanged(int state) throws RemoteException {
118 mHandler.obtainMessage(MSG_CALL_STREAMING_CHANGED_CHANGED, state).sendToTarget();
119 }
120 }
121
122 /**
123 * Call streaming request reject reason used with
124 * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
125 * call streaming request because there's an ongoing streaming call on this device.
126 */
127 public static final int STREAMING_FAILED_ALREADY_STREAMING = 1;
128
129 /**
130 * Call streaming request reject reason used with
131 * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
132 * call streaming request because telecom can't find existing general streaming sender on this
133 * device.
134 */
135 public static final int STREAMING_FAILED_NO_SENDER = 2;
136
137 /**
138 * Call streaming request reject reason used with
139 * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
140 * call streaming request because telecom can't bind to the general streaming sender app.
141 */
142 public static final int STREAMING_FAILED_SENDER_BINDING_ERROR = 3;
143
144 private StreamingCallAdapter mStreamingCallAdapter;
145 private StreamingCall mCall;
146
147 /**
148 * @hide
149 */
150 @IntDef(prefix = {"STREAMING_FAILED"},
151 value = {
152 STREAMING_FAILED_ALREADY_STREAMING,
153 STREAMING_FAILED_NO_SENDER,
154 STREAMING_FAILED_SENDER_BINDING_ERROR
155 })
156 @Retention(RetentionPolicy.SOURCE)
157 public @interface StreamingFailedReason {};
158
159 /**
160 * Called when a {@code StreamingCall} has been added to this call streaming session. The call
161 * streaming sender should start to intercept the device audio using audio records and audio
162 * tracks from Audio frameworks.
163 *
164 * @param call a newly added {@code StreamingCall}.
165 */
166 public void onCallStreamingStarted(@NonNull StreamingCall call) {
167 }
168
169 /**
170 * Called when a current {@code StreamingCall} has been removed from this call streaming
171 * session. The call streaming sender should notify the streaming receiver that the call is
172 * stopped streaming and stop the device audio interception.
173 */
174 public void onCallStreamingStopped() {
175 }
176
177 /**
178 * Called when the streaming state of current {@code StreamingCall} changed. General streaming
179 * sender usually get notified of the holding/unholding from the original owner voip app of the
180 * call.
181 */
182 public void onCallStreamingStateChanged(@StreamingCall.StreamingCallState int state) {
183 }
184}